由于JavaScript的
this
不同于C++、JAVA等语言,在开发中容易造成一些困扰,故总结一下Javascript中的this
知识,以免踩坑。
个人博客原文链接:点此前往
this指向问题
一般情况
this
的指向不是由函数定义在哪个对象里面决定的,而是函数执行时由谁”唤醒”或者说调用来决定的,即调用时才对this
做绑定,而不是定义时。
箭头函数
如果用babel解析后可以发现,箭头函数本身并没有this
,而是按照词法作用域来绑定上下文。所以箭头函数的this
实际上指向的是原来的上下文(向上找一层)。
并且不同于一般的this绑定,箭头函数的this
指向是在定义时确定(绑定上下文)的,并且一旦确定就不会被改变。
立即执行函数
立即执行函数的this
指向window。但在严格模式下,其this
指向undefined
example
例子来源: 《你不知道的JavaScript(上卷)》
var name = "Jay Global";
var person = {
name: 'Jay Person',
details: {
name: 'Jay Details',
print: function() {
return this.name;
}
},
print: function() {
return this.name;
}
};
/**
* result: Jay Details
* reason: 这里的print是由person.details调用的,所以this的指向为details
* */
console.log(person.details.print());
/**
* result: Jay Person
* reason: 这里的print是由person调用的,所以this的指向为person
* */
console.log(person.print());
var name1 = person.print;
var name2 = person.details;
/**
* result: Jay Global
* reason: 这里的name1实际上就是一个function,无调用对象。
* 也可以看作是window调用的,所以this指向window。
* */
name1();
/**
* result: Jay Detail
* reason: 这里的name2是一个Object,所以是name2调用了自身的一个函数。
* 该函数的this指向name2这个对象。
* */
name2.print();
修改this的指向
修改this
的指向,主要有以下三方法: call、apply、bind
bind
语法:func.bind(this, [arg1, arg2...])
bind方法由函数调用,接收一个对象参数以及其他参数(可选)。bind会将func的this
指向绑定的第一个参数上,后续传入的参数会绑定到func里作为传入参数。最后返回一个this
经过改变的func。
应用场景:1、函数柯里化 2、函数借用(如下例)
let a = function () {
let show = 1;
console.log(this.show)
}
let b = {
show: 2
}
let c = a.bind(b);
c(); // 2
PS: bind的兼容性不好,ES3不支持,但我们可以手动创建一个bind:
// bind函数ES3实现
if (!Function.prototype.bind) {
Function.prototype.bind = function(o/*,args*/){
// 将this和arguments的值保存至变量中,以便在后面的嵌套函数中调用
var self = this;
var boundArgs = arguments;
// bind()返回一个函数
return function() {
// 创建一个实参列表,将传入bind()的第二个及后续的实参都传入这个函数
var args = [], i;
for(i = 1; i < boundArgs.length; i++) args.push(boundArgs[i]);
for(i = 0; i < arguments.length; i++) args.push(arguments[i]);
return self.apply(o, args);
}
}
}
call & apply
语法:func.call(this, [arg1, arg2...])
、apply.bind(this, [Array])
1、call和apply用法与bind大致相同,不同之处在于call和apply使用后会立即执行更改this
指向后的函数,而不是像bind那样返回
2、call和apply的区别在于:call除了第一个参数以外,可以像bind那样接收多个参数进行绑定。而apply则是接收一个数组。
apply由于可以接收数组,更适合用于数目可变的参数绑定。
但是由于多了一步解析数组参数的过程,会比call处理速度稍稍慢些,因此在参数少且不变的情况下建议用call。