Hello,各位。前几天在开发的过程中,又遇到了this这个难搞的东西,虽然很多大佬认为这个是javascript语言的败笔,但是没办法,还是得深入了解一下,于是乎,还是总结一下。接下来分析this经常碰到的几种场景。
默认绑定
默认绑定一般就是说直接调用方法,这种情况下,this指向全局对象,例如:
function a(){
console.log(this);
}
funciton b(){
a();
}
b(); //window
当然,在对象中调用也是如此,例如:
function a(){
console.log(this);
}
const b = {
c(){
a();
}
}
b.c(); //window
当然这种情况下,个人认为和静态词法作用域也有显著的关联,这里就不做详述了。 不过要注意'use strict'的问题,如果加了'use strict',那调用方法始终是undefined,例如:
'use strict'
function a(){
console.log(this);
}
const b = {
c(){
a();
}
}
b.c(); //undefind
隐式绑定
在对象中定义方法,这种还是经常遇到的,但是一般也比较好判断,this指向定义它的对象,例如:
const a = {
b(){
console.log(this)
}
}
a.b(); //{b: ƒ}
当然,对象引用定义的方法也是一样,例如:
function b(){
console.log(this);
}
const a = {
b
}
a.b(); //{b: ƒ}
其实这里可以看到已经不受词法作用域的影响了。
new绑定
这个大家肯定轻车熟路,毕竟面试啊要考,更加是写得多。首先是new参数执行的默认操作:
- 创建构造函数的原型对象的对象(Object.create(构造函数.prototype)),这部分其实和es6以前知识的有关。
- 将构造函数的方法的this指向第一步创建的对象,并执行这个构造函数。
- 判断构造函数有木有返回其它参数,有返回就返回这个参数,没有就返回执行完成后的第一步的对象。
浓缩成代码就是:
function create (par = function () { }, ...args) {
const create = Object.create(par.prototype);
const res = par.apply(create, args);
return res instanceof Object ? res : create;
}
所以经过上述步骤,作为构造函数的方法内部的this就必定可以确定。当然es6中的class一样,这里就不展开了。
强制绑定
这个就是各个javascript框架中喜爱的call,bind,apply,了,例如:
function b(){
console.log(this);
}
const a = { }
b.call(a);
b.apply(a);
b.bind(a)()
至于这三个方法的区别,我相信懂滴都懂~。
总结
差不多就这些,笔者主要参照《你不知道的javascript》,这本书在github上中英文都有,大家可以去看看。虽然翻译之后的中文还是那么的大妈之意,晦涩难懂,但是多看几遍还是会眼前一亮的。