JavaScript this
this用的很多,react 的class component用了这么多自己也比较熟悉的了,下面就来讲讲如何判断一个this的绑定以及call、apply、bind的实现。
判断this绑定
主要就是以下的几点:
- 由new调用:绑定到新创建的对象上面。在类里面的contructor中,指向将要通过构造器创建的对象。
- 由call、apply、bind来调用,绑定到指定的对象上面。
- 由上下文对象调用,就绑定到上下文的对象上面。
- 默认:全局对象,node为global,浏览器为window
如何实现call
Function.prototype.call = function(context) {
var context = Object(context) || window;
// call是由一个函数调用的,此时this就指向该函数
context.fn = this;
var args = [];
for(let i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']');
}
var res = eval('context.fn(' + args + ')');
delete context.fn;
return res;
}
var obj = {
a: 1
}
function print() {
console.log(this.a)
}
print.call(obj);
如何实现apply
apply与call的最大区别就是,apply仅有第二个参数apply(obj, arguments),且arguments为一个数组,数组里面存放了要传递给调用call方法的函数的参数
而call则一个一个的接收参数call(obj, argument1, argument2, argument3, ... argumentn)
Function.prototype.apply = function(context, arr) {
var context = Object(context) || window;
context.fn = this;
var res;
if(!arr) {
res = context.fn();
} else {
var args = [];
for(let i = 0; i < arr.length; i++) {
args.push('arr[' + i + ']');
}
res = eval('context.fn(' + args + ')');
}
delete context.fn;
return res;
}
var obj = {
a: 1
}
function bar(b, c) {
return {
a: this.a,
b: b,
c: c
}
}
bar.apply(obj, [2,3])
如何实现bind
Function.prototype.bind = function(context) {
if(typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.call(arguments, 1);
var fNOP = function() {};
var fBound = function() {
self.apply(this instanceof self ? this :context, args.concat(Array.prototype.slice.call(arguments)));
}
fNOP.prototype = this.prototype;
fbound.prototype = new fNOP();
return bound;
}