this-函数内部的一个特殊对象,引用的是函数执行的环境对象
在函数调用前,this值并不确定。
也就是说,this是在函数执行时被绑定的,取决于函数的调用位置。
全局作用域中调用函数,this对象引用的是window
改变this指向
1.apply、call、bind
window.color = 'red';
var obj = {color: 'blue'};
function sayColor () {
console.log(this.color);
}
sayColor(); //'red'
sayColor.call(obj); //'blue'
sayColor.apply(obj); //'blue'
2.构造函数中
this会指向实例对象
function People (name){
this.name = name;
}
const child = new People('xiaopengyou');
console.log(child.name); //xiaopengyou
3.作为对象方法被调用
this指向该对象
window.color = '1';
var obj = {color: '2'};
function sayColor () {
console.log(this.color);
}
obj.osay = sayColor;
obj.osay(); //'2'
3.闭包中的this
匿名函数的执行环境具有全局性,因此其this对象通常指向window。
有时编写闭包的方式不同,这一点可能并不明显。
- 每个函数在被调用时都会自动取得两个特殊变量:this、argument。
- 内部函数在搜索这两个变量时,只会搜索到其活动对象为止;
- 因此永远不能访问外部函数中的这两个变量。
但是可以通过将外部作用域中的this对象保存在一个闭包能访问的变量里
var name = 'The Window';
var obj = {
name:'obj',
sayName: function(){
var that = this; //保存外部作用域中的this对象‘obj’
return function(){
console.log(this.name);//'The Window'
return that.name;//'obj'
}
}
}
console.log(obj.sayName()());
var name = 'The Window';
var obj = {
name:'obj',
sayName: function(){
var that = this; //保存外部作用域中的this对象‘obj’
return function(){
console.log(this.name);//'The Window'
return that.name;//'obj'
}
}
}
console.log(obj.sayName()());
匿名函数的执行环境具有全局性
var name = 'window';
const user = {
name: 'user',
action: {
name: 'action',
getCount: function(){
return this.name;
}
//getCount:()=>this.name,
}
};
const action = user.action;
const getCount = user.action.getCount;//这个赋值表达式的值是函数本身,
//所以this的值不能得到维持
console.log(user.action.getCount());//this:action 箭头:window
console.log(action.getCount());//this:action 箭头:window
console.log(getCount());//this:window 箭头:window
4.箭头函数中
- this对象是定义时所在的对象,而不是使用时所在的对象
箭头函数可以让this指向固化,固化并不是因为箭头函数内部有绑定this的机制
实际原因是,箭头函数**根本没有自己的this,导致内部的this就是外部代码块的this**。
function Timer () {
this.n = 10;
this.m = 20;
//箭头函数
setTimeout(() => {
this.n += 1; //this指向Timer
},100);
//普通函数
setTimeout(function(){
this.m += 1; //this指向window
},100);
}
var timer = new Timer();
setTimeout(() => console.log('n',timer.n),200);//11
setTimeout(() => console.log('m',timer.m),200);//20
- setTimeout执行时所在的作用域为window(this)**上述m不变
- 箭头函数使其里面的this绑定定义时所在的位置 **n改变
var btn = document.getElementById('btn');
btn.addEventListener('click',function(){console.log(this)}); //button
btn.addEventListener('click',() => {console.log(this)}); //window
var handler = {
message: 'handler',
click: function (){
console.log(this);
}
}
//btn.addEventListener('click',handler.click); //button
btn.addEventListener('click',function(){
console.log(this,'this')//button
handler.click(); //指向handler对象
});
function Timer () {
this.n = 10;
this.m = 20;
//箭头函数
setTimeout(() => {
this.n += 1; //this指向Timer
},100);
//普通函数
setTimeout(function(){
this.m += 1; //this指向window
},100);
}
var timer = new Timer();
setTimeout(() => console.log('n',timer.n),200);//11
setTimeout(() => console.log('m',timer.m),200);//20
var btn = document.getElementById('btn');
btn.addEventListener('click',function(){console.log(this)}); //button
btn.addEventListener('click',() => {console.log(this)}); //window
var handler = {
message: 'handler',
click: function (){
console.log(this);
}
}
//btn.addEventListener('click',handler.click); //button
btn.addEventListener('click',function(){
console.log(this,'this')//button
handler.click(); //指向handler对象
});
5.在class方法中调用
原型继承
function A(x){
this.x = x;
}
A.prototype.x = 1;
function B(x){
this.x = x;
}
B.prototype = new A();
var a = new A(2);
var b = new B(3);
delete b.x;
console.log(a.x,b.x); //2 undefined
var handler = {
message: 'handler',
click: function (){
console.log(this);
}
}
var btn = document.getElementById('btn');
//btn.addEventListener('click',handler.click); //button
btn.addEventListener('click',function(){
console.log(this,'this')//button
handler.click(); //指向handler对象
});
var bar = {
myname: "bar", //注意。不是变量,字符串
getName: function() {
console.log(myname);
console.log(this);
}
}
function foo() {
var myname = "foo";
return bar.getName;
}
var myname = "global";
var _printName = foo();
_printName(); //"global" window
bar.getName(); //"global" bar对象