前端工程师面试知识库:JavaScript相关

JavaScript相关
1 ["1", "2", "3"].map(parseInt)
首先, map接受两个参数, 一个回调函数 callback, 一个回调函数的this值

其中回调函数接受三个参数 currentValue, index, arrary;

而题目中, map只传入了回调函数--parseInt.

其次, parseInt 只接受两个两个参数 string, radix(基数).  
本题理解来说也就是key与 index 

所以本题即问
parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);

parseInt(string, radix)
string	必需。要被解析的字符串。
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。
复制代码
2 [[3,2,1].reduce(Math.pow), [].reduce(Math.pow)]
arr.reduce(callback[, initialValue])
reduce接受两个参数, 一个回调, 一个初始值.
回调函数接受四个参数 previousValue, currentValue, currentIndex, array
需要注意的是 If the array is empty and no initialValue was provided, TypeError would be thrown.
所以第二个表达式会报异常. 第一个表达式等价于 Math.pow(3, 2) => 9; Math.pow(9, 1) =>9
复制代码
3
var ary = [0,1,2];
ary[10] = 10;
ary.filter(function(x) { return x === undefined;});
我们看到在迭代这个数组的时候, 首先检查了这个索引值是不是数组的一个属性, 那么我们测试一下.

0 in ary; => true
3 in ary; => false
10 in ary; => true
也就是说 从 3 - 9 都是没有初始化的bug !, 这些索引并不存在与数组中. 在 array 的函数调用的时候是会跳过这些坑的.
复制代码
4 [typeof null, null instanceof Object]
typeof 返回一个表示类型的字符串.
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上.
type         result
Undefined   "undefined"
Null        "object"
Boolean     "boolean"
Number      "number"
String      "string"
Symbol      "symbol"
Host object Implementation-dependent
Function    "function"
Object      "object"
复制代码
5 js数据类型

1.number;

2.string;

3.boolean;

4.undefined;

5.null;

6.symbol(ES6新增,文章后面有对着新类型的解释)Symbol 生成一个全局唯一的值。

7.Object.(包括Object,Array,Function)

6 promise 用法
定义
var promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
使用
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
//等价于:
promise.then(function(){
  //success
}).catch(function(){
  //failure
})
复制代码
7 es6 promise ajax
定义
const myHttpClient = url => {
  return new Promise((resolve, reject) => {
    let client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();
    function handler() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    }
  });
};
使用
myHttpClient('https://www.baidu.com').then(res => {
  console.log(res);
}).catch(error => {
  console.log(error);
});
复制代码
8闭包
function foo(x) {
    var tmp = 3;
    return function (y) {
        alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);
结果是16
es6通常用let const块级作用域代替,
闭包缺点,ie中会引起内存泄漏,严格来说是ie的缺点不是闭包的问题
复制代码
9 什么是立即执行函数?使用立即执行函数的目的是什么?
常见两种方式
1.(function(){...})()
  (function(x){
	  console.log(x);
  })(12345)
2.(function(){...}())
  (function(x){
	  console.log(x);
  }(12345))
作用 不破坏污染全局的命名空间,若需要使用,将其用变量传入如
(function(window){...}(window))
复制代码
10 async/await 语法
作用:异步代码的新方式
promise示例
const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}
async/await示例
const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}
函数前面多了一个aync关键字。await关键字只能用在aync定义的函数内。async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。(示例中reosolve值就是字符串"done")
复制代码
11 深浅拷贝
let a = {
  aa: 1,
  bb: 2,
  cc: 3,
  dd: {
    ee: 5,
  },
  ff: {
    gg: 6,
  }
};
let d = JSON.parse(JSON.stringify(a));//深复制包含子对象
let c = {...a};//拷贝一层但不包含子对象
let b = a;//浅拷贝
b.bb = 22;
c.cc = 33;
c.dd.ee = 55;
d.ff.gg = 66;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
复制代码
12数组去重
思路1:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中
思路2:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。
思路3:利用对象属性存在的特性,如果没有该属性则存入新数组。
思路4(最常用):使用es6 set
let arr= [1, 2, 3, 3, 5, 7, 2, 6, 8];
console.log([...new Set(arr)]);
复制代码
13正则实现trim()功能
function myTrim(str) {
  let reg = /^\s+|\s+$/g;
  return str.replace(reg, "");
}
console.log(myTrim('    asdf    '));
复制代码
14 JS原型
1.每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性
2.个人粗略理解与python的类方法静态方法实例方法差不多
复制代码

#####15 es6 class

面向对象,java中类
复制代码
16 JS 如何实现继承
1.使用原型继承(既继承了父类的模板,又继承了父类的原型对象。优点是继承了父类的模板,又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法)
2.使用call的方式(继承了父类的模板,不继承了父类的原型对象。优点是方便了子类实例传参,缺点就是不继承了父类的原型对象)
复制代码
17 手写jquery插件
(function ($) {
	$.fn.myPlugins = function (options) {
	  //参数赋值
	  options = $.extend(defaults, options);//对象合并
	  this.each(function () {
	      //执行代码逻辑
	  });
	};
})(jQuery);

$(selector).myPlugins({参数});
复制代码
18 数组合并去重排序
let arr1 = [1, 25, 2, 26, 1234, 6, 213];
let arr2 = [2, 6, 2134, 6, 31, 623];
let c = [...new Set([...arr1, ...arr2])].sort((a, b) => {
	return a - b;
});
复制代码
19 call apply

作用:在函数调用时改变函数的执行上下文也就是this的值 区别:call采用不定长的参数列表,而apply使用一个参数数组。 性能优化图

性能优化
20 for 中setTimeOut

要为循环题创建不同的循环副本

21 sort函数

V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 插入,比10大的数组则使用 快排。

22 navigator
Navigator
23 jquery绑定方式
  1. click后者覆盖
  2. bind后者覆盖
  3. on(jquery>=1.7)
  4. live
  5. delegate
24 事件流向
  1. 冒泡:子节点一层层冒泡到根节点
  2. 捕获顺序与冒泡相反
  3. addEventListener最后个参数true代表捕获反之代表冒泡
  4. 阻止冒泡不停止父节点捕获
25原生操作class
//判断有无
function hasClass(ele, cls) {
	return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
}

//添加
function addClass(ele, cls) {
	if (!this.hasClass(ele, cls)) ele.className += " " + cls;
}

//删除
function removeClass(ele, cls) {
	if (hasClass(ele, cls)) {
		let reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
		ele.className = ele.className.replace(reg, " ");
	}
}

html5中加入classList 
一系列操作
兼容至IE10

作者:信心
链接:https://juejin.im/post/5b94d8965188255c5a0cdc02
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

THE END