在 Javascript中 this
的指向不是固定不变的,它会随着执行环境的改变而改变。但它始终会指向该方法运行时所在的环境(调用函数的那个对象)。
函数和方法区别: 方法依赖对象调用,函数不依赖对象。
本文以浏览器中的Javascript环境讲解,而非Node环境。
在全局作用域中,无论是否为严格模式,this
指向的都是window
对象。
console.log(this===window);
"use strict";
console.log(this===window);
默认绑定:函数调用时无任何调用前缀,该函数将会自动绑定到window
对象(全局对象),使之成为window
对象的一个方法。也就是说该函数实际有个隐式前缀window
。故全局作用域中普通函数this
指向的是window
对象。
function foo(){
console.log(this===window);
}
foo();
window.foo();
由于非严格模式下有些写法其实是不大符合逻辑的,比如在顶级作用域中使用var
声明的变量会自动成为全局变量,还有调用普通方法时会自动将方法绑定到window
对象中。
严格模式中顶级作用域下调用普通函数的时候,不会自动将函数绑定到window
对象,导致函数的调用者丢失,此时函数内的this
相当于未初始化的普通变量,为undefined
。
"use strict";
function foo(){
console.log(this===window);
}
foo();
window.foo();
无论是否为严格模式,如果函数调用时,前面存在调用它的对象,那么this
就会隐式绑定到这个对象上(多个对象在前,采用最近原则)
var obj = {
innerObj: {
foo: function() {
console.log(this);
}
}
};
obj.innerObj.foo();
var func=obj.innerObj.foo
func();
"use strict";
var obj = {
innerObj: {
foo: function() {
console.log(this);
}
}
};
obj.innerObj.foo();
var func=obj.innerObj.foo
func();
隐式丢失就是指隐式绑定的函数丢失绑定对象,从而默认绑定到全局或者undefined(取决于是否使用严格模式)
无论是否为严格模式,通过call
、apply
以及bind
方法改变this
的行为,this
都指向绑定的对象。需要注意的是非严格模式下使用call之类的方法改变this
指向时,指向参数提供的是null
或者undefined
,那么 this
将指向全局对象。
var name = 'Joe';
var obj = {
name: 'Free',
fn: function() {
console.log(this.name);
}
};
var obj2={name:'Fly'}
obj.fn.call(obj2)
obj.fn.call(null)
obj.fn.apply(obj2)
obj.fn.bind(obj2)()
"use strict";
var name = 'Joe';
var obj = {
name: 'Free',
fn: function() {
console.log(this.name);
}
};
var obj2={name:'Fly'}
obj.fn.call(obj2)
obj.fn.call(null)
obj.fn.apply(obj2)
obj.fn.bind(obj2)()
无论是否为严格模式,只要是通过构造函数new
对象,构造函数中的this都指向这个新对象。
new的时候会做下面这四件事:
(1)开辟内存空间,在内存中创建一个新的空对象。
(2)让 this 指向这个新的对象。
(3)执行构造函数里面的代码,给这个新对象添加属性和方法。
(4)返回这个新对象(所以构造函数里面不需要 return)
let Dog = function (name, age) {
this.name = name;
this.age = age;
};
const myDog = new Dog();
function Person(){
this.name=name
}
let Joe=new Person('Joe')
console.log(Joe.name);
"use strict";
function Person(){
this.name=name
}
let Joe=new Person('Joe')
console.log(Joe.name);
如果在某个调用位置应用了多条规则,如何确定哪条规则生效?
显式绑定 > 隐式绑定 > 默认绑定
new绑定 > 隐式绑定 > 默认绑定
obj.foo.call(obj2);
new obj.foo();
箭头函数的this
指向取决于外层作用域(最近的那个)中的this
,外层作用域或函数的this
指向谁,箭头函数中的this
便指向谁。
箭头函数的 this
一旦绑定了上下文,就不会被任何代码改变。
var foo=()=>{
console.log(this);
}
var obj={}
foo.call(obj);
"use strict";
var foo=()=>{
console.log(this);
}
var obj={}
foo.call(obj);
在事件中,this 表示接收事件的元素。
<input type="text" onclick="this.value=this" placeholder="点击查看事件中this指向"/>