this的指向存在以下几种场景:
1-1 new 绑定
- 构造函数被new调用
class A {
constructor(a,b) {
this.a = a;
this.b = b
}
func1() {
console.log(this.a) // 1
}
}
const bar = new A(1,2) // 输出: bar实例,这里的this就是bar
可以看出,作为构造函数new调用的时候。this指向的是新创建的构造函数的实例
这里顺便解释下new的过程:
- 创建一个新的对象 object
- 把构造函数的prototype赋值给这个新对象的_proto_,即
object. _proto_ = A.prototype- 把新的对象赋值给当前的this;
this = object- 执行构造函数 A()
- 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象,如果返回的不是对象,将会被忽略
1-2 显示绑定
- 作为对象的方法使用,使用call, apply,bind改变this指向;
function attribute(name, height) {
this.name = name
this.height = height
}
function Person(name, height, occupation) {
attribute.call(this, name, height) // call 方式调用
// attribute.bind(this, name, height) // bind 方式调用
// attribute.apply(this, [name, height]) // apply 方式调用,跟一个数组
this.occupation = occupation
}
new Person('tiger', 178, '前端开发')
- 顺便理一下bind的实现原理
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。
Function.prototype.bind = (context) => {
let self = this;
const args = Array.prototype.slice.call(arguments, 1);
const Temp = function() {}
const Bind = function() {
let args2 = Array.prototype.alice.call(arguments);
// 当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效
return self.apply(this instanceof temp ? this : context, args.concat(args2));
}
Temp.prototype = this.prototype; // 修改返回函数的prototype为绑定函数的prototype,实例就可以继承函数绑定中的值,其实是Bind.prototpe = self.prototype, 但若是直接修改Bind的原型,会直接修改绑定函数的prototype,所以接触中转函数Temp来实现
Bind.prototype = new Temp();
return Bind
}
1-3 隐式绑定
- 函数在某个上下文中调用,this绑定的就是当前的上下文
let a = 'javascript';
const obj = {
a: 'css',
func: function() {
console.log(this.a)
}
}
obj.func() // css
这里可以看出this的指向就是指向obj,同样我们再看看另一种情况
var a = 'javascript'
var obj = {
a: 'css',
b:{
a:'html',
func: function() {
console.log(this.a)
}
}
}
obj.b.foo() // 浏览器中输出: "html",这里的this指向 b
通过以上两个例子,可以得出结论,隐式调用的this指向: 就是指向当前调用该函数的上下文, 如果嵌套了多个对象,那么指向最后一个调用这个方法的对象。
1-4 默认绑定
- 在不使用任何修饰的函数进行调用(即不包括以上三种情况); 非严格模式下this 绑定到全局对象(浏览器下是 winodw,node 环境是 global),严格模式下 this 绑定到 undefined (因为严格模式不允许 this 指向全局对象)。
let a = 'javascript';
function func1() {
let a = 'css';
console.log(this.a);
}
func() // javascript, 这里的this就是默认绑定,指向window
- this指向当前函数执行的上下文(理解这句话很重要)
2.this绑定的优先级
new 绑定 > 显示绑定 > 隐式绑定 > 默认绑定