基础部分
1.JS中使用typeof
能得到哪些类型?(JS变量类型)
- 空类型
null(=>object)
undefined
- 值类型
number
string
boolean
- 引用类型 (对象、数组)
object
function
1.1 JS内置函数
- Number, String, Boolean, Object, Array, Function, RegExp, Date, Error
- 内置对象Math, JSON
2.使用===
与==
的区别(类型强转)
==
用于弱比较,如下面都成立100=='100'
,0 == null
,null==undefined
===
用于严格比较,上述例子都不成立,返回false
- 实际开发中,除了要判断
null
与undefined
外,其他比较建议都使用3等号===
(Jquery源码的建议)
3. instanceof是如何执行的(原型与原型链)
obj.__proto__ === Object.prototype
(__proto__指向其构造函数的prototype),- 每个对象都有
__proto__
,每个函数都有prototype
arr instanceof Array
。arr.__proto__
隐式原型查找是否等于Array的显示原型Array.prototype
Object instanceof Function
,Function instanceof Object
// true
3.1 写一个继承例子
- 对象可通过原型链进行继承
来自原型对象的所有属性被所有实例共享
如果要新增原型属性和方法,则必须放在 childComponent.prototype = new parentComponent(); 这样的语句之后执行
// 父级函数
function parentComponent(name) {
this.name = name;
this.alert = function() {
alert('parentComponent alert');
}
}
// 父级方法
parentComponent.prototype.prototypeAlert = function() {
alert('parentComponent.prototype.prototypeAlert')
}
// 子级函数
function childComponent() {
}
// 继承
childComponent.prototype = new parentComponent();
// 实例化 并调用父级方法
var c = new childComponent();
c.alert();
c.prototypeAlert();
- 通过call进行继承
只能继承父类的实例属性和方法,不能继承原型属性/方法
无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
// 父级函数
function parentComponent(name) {
this.name = name;
this.alert = function() {
alert('parentComponent alert');
}
}
// 子级函数
function childComponent(name) {
// 继承
parentComponent.call(this, name)
}
// 实例化 并调用父级方法
var c = new childComponent();
c.alert();
4.实现数组的随机排序(基础算法)
4.1 数字类型数组小到大排序
let numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
4.2 数组随机排序
不太严谨的写法
let strArr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'];
strArr.sort((a, b) => Math.random() - 0.5);
console.log(strArr);
相对严谨的写法1
let strArr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'];
let strObjArr = [];
strArr.forEach((str, index) => {
strObjArr.push({str, index, r: Math.random()})
})
strObjArr.sort((a, b) => a.r-b.r);
console.log(strObjArr);
相对严谨的写法2(推荐)
let strArr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'];
shuffle(strArr);
function shuffle(arr) {
var i = arr.length, t, j;
while (i) {
j = Math.floor(Math.random() * i--);
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
// es6
function shuffleES6(arr) {
var i = arr.length;
while(i) {
j = Math.floor(Math.random() * i--);
[arr[j], arr[i]] = [arr[i], arr[j]];
}
}
4.3 数组去重
// es5
let strArr = ['a', 'b', 'c', 'd', '1', 'f', 'g', 'a', 'b', 'c', '1'];
let result = strArr.filter((item, index, arr) => arr.indexOf(item) === index);
console.log(result);
// es6
let strArr = ['a', 'b', 'c', 'd', '1', 'f', 'g', 'a', 'b', 'c', '1'];
let result = [...new Set(strArr)];
console.log(result);
5.apply、bind、call
- 三者都可以通过第一个参数来改变
this
的引用 apply
第二个参数是一个数组 func.apply(thisArg, [argsArray]),而call
和bind
第二之后的参数同样是对应的函数参数列表function.bind(thisArg[, arg1[, arg2[, ...]]])
,function.call(thisArg, arg1, arg2, ...)
bind
返回值是一个绑定函数- 从性能方面,相比之下
call
较优,因此用得较多
6.闭包
闭包也可以理解为背包。自由变量的值是根据函数声明定义时的上下文,而不是函数执行时的上下文
使用场景
- 函数作为返回值
- 函数作为参数进行传递
参考代码
- 函数作为返回值
function func() {
var a = 100;
return function() {
console.log(++a);
}
}
var a = 200;
var fn = func();
fn(); // 101
- 函数作为参数进行传递
function func() {
var a = 100;
return function() {
return ++a;
}
}
function run(fn) {
var a = 200;
var res = fn();
console.log(res());
}
run(func); // 101