定义
简单的说
this就是属性或方法运行时,当前所在的对象。和运行时所处的环境相关,而与编写代码时所在位置无关(ES5)。
- 常规操作(1)
//最常见的用法
var A = {
name: '张三',
describe: function () {
return '姓名:'+ this.name;
}
};
this属于方法describe,而方法describe又属于对A,所以this是指向的对象A,在这个时候this.name等同于a.name
- 常规操作(2)
function f() {
return '姓名:'+ this.name;
}
var A = {
name: '张三',
describe: f
};
var B = {
name: '李四',
describe: f
};
var C = {
name: '赵六',
describe: function{
return '姓名:'+ this.name;
}
};
var name='王五'
var f2=C.describe
A.describe() // "姓名:张三"
B.describe() // "姓名:李四"
f() // "姓名:王五"
f2() //"姓名: 赵六"
由于
this指向是根据环境变化的,所以A.describe()方法B.describe()输出的结果会不同,因为f方法的所在的对象变了。所以this指向改变了(注意: nodejs和浏览器环境下,this所指向的全局对象不一样,所以输出结果会不同。nodejs中f() 输出的为undefined,话说这个坑困扰了我很久!!)
常见的坑
由于
this只针对的指向不明确,所以会经常有各种坑。下面来列举一下几个常见的:
- 函数自执行的时候,
this指向的事全局对象Window。先看一个复杂点的例子:
var o = {
f1: function () {
console.log(this);
var f2 = function () {
console.log(this);
}();
}
}
o.f1()
// Object (f1中输出的事对象o)
// Window (f2中输出的是全局对象Window)
上述情况中
this的指向,与我们想要的结果明显不符,上述代码实际执行的为:
var temp = function () {
console.log(this);
};
var o = {
f1: function () {
console.log(this);
var f2 = temp();
}
}
函数自执行的定义:函数名+()的调用方式叫做自执行。 上面的temp()就是函数名加括号的调用方式,所以是自执行。
var f2 = function () {
console.log(this);
}();
//上述代码实际上可以转换为:
var f2 = function () {
console.log(this);
};
f2(); //自执行
那么问题来了,为什么上述的o.f1()的时候,f1中的
this指向的是对象o而不是全局对象window呢?答案在于方法和函数的区别,o.f1()表示的是调用的对象o中的方法,而f2()则表示的是调用函数f2(),它们最大的区别,就是有没有通过对象来调用。
知道区别了,接下来看看其他例子:
function fn(){
console.log(this); //Window
}
fn(); //最常见的自执行,函数加括号。以前只知道是指向全局,现在知道为什么了
ES6箭头函数中的this
箭头函数是ES6中新增的一种简洁的函数书写方式,基本语法是:
参数 => 函数体。 之所以把箭头函数单独拿出来说,是因为箭头函数与我们常见的函数,有很多不同之处,this的指向就是区别之一。
箭头函数
this的定义:箭头函数的中没有this,所以箭头函数中的this是直接继承(或者说调用)父级的this,并且箭头函数的this是在定义时绑定,所以和运行环境无关,这点和普通函数相反。
- 箭头函数
this的例子:
var x = 11;
var obj = {
x: 22,
say: () => {
console.log(this.x);
},
say2: function () {
console.log(this.x);
}
}
obj.say(); //输出11
obj.say2(); //输出22
//1.因为继承的是父级的this,而父级的this指向的是全局,所以say()拿到的数据是11
//2.第二个普通方法,所以拿到的是x=22
setTimeout的this
先举个常见的栗子:
var Person = {
'age': 18,
'sayHello': function () {
setTimeout(function () {
console.log(this.age);
});
}
};
var age = 20;
Person.sayHello(); // 20
var Person1 = {
'age': 18,
'sayHello': function () {
setTimeout(()=>{
console.log(this.age);
});
}
};
var age = 20;
Person1.sayHello(); // 18
Person1.sayHello();还比较好理解,因为使用了箭头函数,所以this继承自sayHello对象中this,而sayHello对象的this指向的是Person1对象。所以Person1.sayHello()中的this.age实际上是Person1.age。那么为什么
Person.sayHello()中console.log(this.age)输出的是20呢? 答案是由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的 this 关键字在非严格模式会指向 window (或全局)对象,严格模式下为 undefined,这和所期望的this的值是不一样的。