Alanxz 2020-03-04
call
func.call(context, arg1, arg2, ...)
参数说明:
context :在 func函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
arg1, arg2:…指定的参数列表。
返回值:
使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined。
apply(与call相似,只是参数不同而已)
func.apply(context, arr)
参数说明:
context :在 func函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
arr 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。
bind
func.bind(context, arg1, arg2, ...)
参数说明:
context :在 func函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
arg1, arg2:…指定的参数列表。
返回值:
返回一个原函数的拷贝,并拥有指定的this值和初始参数。
例如:
var name = ‘小王‘, age = 17;
var obj = {
name: ‘小张‘,
age: this.age,
myFun: function(fm, t) {
console.log(this.name + ‘ 年龄‘ + this.age, ‘ 来自‘ + fm + ‘去往‘ + t);
}
}
var db = {
name: ‘德玛‘,
age: 99
} // 以下将obj的myFun方法应用到db对象上
obj.myFun.call(db,‘成都‘,‘上海‘); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.apply(db,[‘成都‘,‘上海‘]); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,‘成都‘,‘上海‘)(); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,[‘成都‘,‘上海‘])(); // 德玛 年龄 99 来自 成都, 上海去往 undefined区别
1、都是用来改变函数的this对象的指向的,this指向他们的第一个参数。
2、call跟apply的用法几乎一样,唯一的不同就是传递的参数不同,call只能一个参数一个参数的传入。
apply则只支持传入一个数组,哪怕是一个参数也要是数组形式。最终调用函数时候这个数组会拆成一个个参数分别传入。
3、bind方法是直接改变这个函数的this指向并且返回一个新的函数,之后再次调用这个函数的时候this都是指向bind绑定的第一个参数。bind传参方式跟call方法一致。
4、如果第一个参数为null或undefined,则this值会自动指向全局对象(浏览器中就是window对象)。
call/apply/bind的核心理念:借用方法。借助已实现的方法,改变方法中数据的this指向,减少重复代码,节省内存。
手写call、apply和bind
// 通过隐式绑定实现
Function.prototype.call = function(context, ...args) {
// 如果没有传或传的值为空对象 context指向window
context = context || window;
// 给context添加一个方法 指向this
context.func = this;
if (typeof context.func !== ‘function‘) {
throw new TypeError(‘call must be called on a function‘);
}
// 执行func
let res = context.func(...args);
// 删除方法,否则context就无缘无故多了个func
delete context.func;
return res;
}Function.prototype.apply = function(context, args) {
context = context || window;
context.func = this;
if (typeof context.func !== ‘function‘) {
throw new TypeError(‘apply must be called on a function‘);
}
let res = context.func(...args);
delete context.func;
return res;
}Function.prototype.bind = function(context, ...bindArgs) {
context = context || window;
// func 为调用 bind 的原函数
const func = this;
if (typeof func !== ‘function‘) {
throw new TypeError(‘Bind must be called on a function‘);
}
// bind 返回一个绑定 this 的函数
return function(...callArgs) {
let args = bindArgs.concat(callArgs);
if (this instanceof func) {
// 意味着是通过 new 调用的 而 new 的优先级高于 bind
return new func(...args);
}
return func.call(context, ...args);
}
}