this对象是在运行时,基于函数的执行环境绑定的。指向大致分为四种:
1)对象的方法调用,this = 该对象;
2)普通函数,this = window;
3)构造器;
4)Function.prototype.call/apply
var a = 2
var obj = {
a: 1,
getValue: function(){
console.log(this.a)
},
// 箭头函数 改变this指向 this = window
getArrowValue: () => {
console.log(this.a)
}
}
// getValue方法是作为obj对象的属性被调用的,this = obj
obj.getValue() // 1
obj.getArrowValue() // 2
// 属于普通函数调用,this = window
var f1 = obj.getValue
f1() // 2
如果对象中的方法返回一个匿名函数,涉及到闭包,情况就不一样了。
var a = 2
var obj = {
a: 1,
getValue: function(){
return function(){
console.log(this.a)
}
}
}
obj.getValue()() // 2
函数被调用时,会创建一个执行环境和相应的作用域链,得到两个变量:this、arguments。
内部函数在搜索这两个变量时,只会搜索到其活动对象为止。
解决这类问题,可以在匿名函数外定义一个变量,把this传给变量,
getValue: function(){
const self = this
return function(){
console.log(self.a)
}
}
上述 var f1 = obj.getValue;f1() 属于普通函数调用,this是指向全局对象的。
JS没有类,但是可以从构造器中创建对象,使用new运算符,返回对象,通常情况,构造器里的this是
指向返回的这个对象的。
但是,如果构造器显示的返回一个object类型的对象,返回结果会是该对象;
const MyClass = function() {
this.name = 'qwe';
return {
name: 'asd'
}
}
const obj = new MyClass()
console.log(obj.name) // asd
在一个对象的上下文中应用另一个对象的方法;
作用一样,都是动态的改变this的执行,并立即执行函数。是传入参数的形式不同,第一个参数都是指定函数体内this对象的指向。
(A对象调用B对象的方法)
call是列表:B.call(A, args1,args2)
apply是数组:B.apply(A, arguments)
let obj1 = {
name: 'qwe',
getName: function() {
return this.name
}
}
const obj2 = {
name: 'asd'
}
console.log(obj1.getName()) // qwe
// this指向obj2
console.log(obj1.getName.call(obj2)) // asd
A.apply(null,[1,2,3]) 第一个参数传null,非严格模式下,函数体内的this会指向全局对象(node:global,浏览器:window)
this.name = 'zxc'
let obj1 = {
name: 'qwe',
getName: function() {
return this.name
}
}
console.log(obj1.getName()) // qwe
console.log(obj1.getName.call(null)) // zxc
在这补充一下call和apply的用途
箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。
简单的说,函数在定义时,this就继承了定义函数的对象。
在事件函数里,有一个内部函数func,在事件函数内部调用func,func体内的this会指向window,而不是我们想要的事件函数的this
(ps:参考了JS设计模式和小红书)