《用得上的前端知识》系列 - 你我都很忙,能用100字说清楚,绝不写万字长文
基本概念
类数组:具备与数组特征类似的对象。它有以下特征:
- 可以通过角标调用
- 具有 length 属性
- 可以通过 for 循环或 forEach 方法
call
函数说明
call 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
基本语法
function.call(thisArg, arg1, arg2, ...)
- thisArg,在 function 函数运行时使用的 this 值
- arg1, arg2, ... 指定的参数列表
apply
函数说明
apply 方法调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
基本语法
function.apply(thisArg[, argsArray])
- thisArg,在 function 函数运行时使用的 this 值
- argsArray,可选的,一个数组或者类数组对象。其中的数组元素将作为单独的参数传给 function 函数。
bind
函数说明
bind 方法创建一个新的函数,bind 函数被调用后,将返回一个新的函数,新创建的函数的 this 被指定为 bind 函数的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
基本语法
function.bind(thisArg[, arg1[, arg2[, ...]]])
- 调用绑定函数时作为 this 参数传递给目标函数的值。如果使用 new 运算符构造绑定函数,则忽略该值。
- arg1,arg2,... 当目标函数(返回函数)被调用时,被预置入绑定函数的参数列表中的值。
区别
call 和 apply 的共同点
- 都能改变函数执行时的上下文;
- 调用 call 或 apply 的对象,必须是一个函数;
- 第一个参数都是对象,且 function 的调用者将会指向这个对象,如果不传就是 window。
call 和 apply 的不同点
- 参数个数不同,call 从第 二个参数开始,可以接收任意数量的参数。每个参数会映射到 function 函数相应位置的参数上;
- 参数类型不同,apply 只接收 2 个参数,第二个参数必须是数组或类数组。它们会被转换成类数组传入到 function 中,并且映射到对应的参数上。
call、apply、bind
- 三者都可以改变对象的执行上下文,使用 call 和 apply 时,调用函数是立即执行的,而 bind 则是返回一个函数,需要再次调用才会执行;
- bind 第一个参数的规则与 call、apply 相同,但对于传参则有些不同,既可以在调用 bind 函数时预传参数,也可以在调用返回函数时才传参。
1、对象继承
function animal(a, b) {
this.type = 'animal'
this.behavior = function(){
console.log(this.type+" is running")
}
}
function cat(a, b) {
this.name = 'cat'
//这里 call 的意思就是把 animal 的方法应用到 cat 这个对象身上
//所以 cat 就继承了 animal 的方法
animal.call(this);
}
console.log(new cat())
// cat {name: "wsscat", type: "animal", behavior: ƒ}
// 当然,上面的call方法也能换成apply
// 或者换成bind,不过要调用以下返回函数:animal.call(this)()
// ------------------ 继承的优化 --------------------
如果构造函数this绑定太多属性(比如一些共同方法),在实例化后会造成浪费,为此我们一般会使用原型链来优化,但是使用原型链之后我们的apply和call的继承方法就会失效
为此我们一般使用混合的写法,使用原型链和(apply或者call)方法进行继承
function animal(type) {
this.type = type
this.behavior = function() {
console.log(this.type + " is running")
}
}
animal.prototype.action = function() {
console.log("running")
}
function cat(name, type) {
this.name = name
animal.call(this, type) // 让父的属性创建在子的this上
}
cat.prototype = new animal(); // 让子的原型链指向父的实例(父实例化的对象)
console.log(new cat('wsscat', 'cute'));
(new cat('wsscat')).action() //running
2、借用方法
// 比如,我们想使用 Array 原型链上的方法,可以这样写:
let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));