this指向
this是指包含它的函数作为方法被调用 时所属的对象。(谁调用了我,我就是谁的对象,谁最后调用了我,我就是谁的对象。)
注意:一定是this所在的函数作为方法被调用,才有可能改变this指向,也就是说这个this外面有个函数,被调用了!
- 箭头函数没有自己的this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值
- 匿名函数的this指向所在的方法被调用的那个对象
- 作用域对象—看例1
1、第一个比较牛逼啦
let length = 10;
function fn(){
console.log(this.length);
}
let obj = {
length:5,
method: function(fn){
fn();
arguments[0]();
}
}
obj.method(fn,1);
正确答案:
0
2
谷歌浏览器测试
解析:
①
首先,使用let关键字定义变量, 在规范中要求,不允许重复定义。 在传统的JS习惯中,所有var直接定义的变量,均为window对象的属性。
即window充当了全局作用域对象 那么,如果window中已经存在一个length属性,重复定义length应该是不被允许的。
由于规范中没有对这种情况做明确的规定。
IE浏览器和谷歌浏览器测试结果不一样
②
其次,这道题目重点考察的依然是this指向。 代码开始于 obj.method(fn,1); 然后进入到method方法中 直接调用了
fn(); fn作为method方法的参数,是一个局部变量,这种调用方式 既不等于obj.fn() ,也不等于window.fn()
等价于 scope.fn(); ,也就是作用域对象的调用又因为,this不能打印作用域对象,这时只能显示window 那么第一次fn的执行,打印出的this.length,
就是window.length结果为0
③
然后,是arguments0 这句代码 arguments是一个数组,里面存储了所有的参数。
在本例中,method方法被调用时,传入了两个参数,一个是fn,一个是数字1 因此,arguments[0]即代表fn
又因为,数组是特殊的对象,下标即是特殊的属性名那么arguments0其实等价于: arguments.0();
最终,this.length,就等于arguments.length结果为2
2、函数返回了一个函数表达式形式的声明,而这个调用的调用是在全局环境中,所以其内部的this就是指向window变量对象
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //"The Window"
// object.getNameFunc()返回了一个匿名函数,然后调用执行这个匿名函数。
//因为这个匿名函数不是作为某个对象的方法来调用执行,所以它的this就是window对象
3、对象和箭头函数中的this
var btn = {
name: "点我",
click: function() {
setTimeout(() => {
console.log(this)
}, 1000);
},
show: () => {
console.log(this);
},
hide: function() {
return () => {
console.log(this)
}
}
}
btn.show(); //window 由于箭头函数没有this,且外面没有函数包着,就是指向默认的window对象
btn.hide()(); //btn btn.hide()返回的是箭头函数,**外面有hide方法包着箭头函数,箭头函数this指的是调用hide方法的那个对象**
let temp = btn.hide();
temp(); //btn 同理2
let bb = btn.hide
bb()(); //window 把hide函数给了全局变量bb
btn.click(); //btn 箭头函数所在父级click方法的上下文是btn,因此this指向btn
4、
var x = 11;
var obj = {
x: 22,
y:function(){
console.log(this);
},
z:()=>{
console.log(this);
}
methods: {
x: 33,
say: function() {
console.log(this.x)
},
say2: () => {
console.log(this.x)
}
}
}
obj.methods.say(); //methods 33
obj.methods.say2(); //window 11
obj.y(); // obj
obj.z(); //window
5、定时器与箭头函数(改变this指向方法之一)
var age = 99;
function PersonX() {
this.age = 0;
setTimeout(() => {
this.age++;
console.log(age);
}, 1000);
}
PersonX(); //1
//其实这里的this就是window,本是一个构造函数,但没有实例化对象; 进入PersonX内,全局变量内的age被修改为0,然后一秒之后+1,定时器内是个箭头函数,因此 this.age 的this和定时器内的this都是指的当前作用域对象,因此输出为1