call apply bind 都可以改变函数的this指向
call和apply的区别
参数不同
call 语法
function.call(thisArg,arg1,arg2,…)
Apply 语法
func.apply(thisArg, [argsArray])
可以看到call和apply的第一个参数都是函数在运行时的this值,call之后接收的是参数列表,而apply接收的是数组或者类数组的值 它们的返回值都是调用有指定this值和参数的函数的结果
应用:
- 简单用法
var name = "雪糕"
var o = {
name:'日月当空照'
fn:function(){
console.log(this.name)
}
}
var person = {
name:'小明'
}
o.fn.call(person) // 小明
- 将一个数组添加到另一个数组上
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
- 判断数据类型
let a = {}
Object.toString.prototype.call(a)
bind
语法
function.bind(thisArg[, arg1[, arg2[, ...]]])
- thisArg 作为this参数传递给目标函数
- arg1,arg2 目标函数的参数
- 返回一个新的函数
用法
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// 在 1 秒钟后声明 bloom
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom(); // 一秒钟后, 调用 'declare' 方法
call,apply 和 bind的区别
call和apply 会立即调用,bind是返回新的函数
手写实现call
Function.prototype.call2 = function (context) {
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
var result = eval('context.fn(' + args +')');
delete context.fn
return result;
}
es6
Function.prototype.call2 = function(context, ...reset) {
var context = context || window;
context.fn = this;
var result = context.fn(...reset);
delete context.fn
return result;
}
实现apply
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')')
}
delete context.fn
return result;
}
实现bind
// 第四版
Function.prototype.bind2 = function (context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
参考