JavaScript中的this
先记住两句话:
-
this 的指向在执行时决定,而不是定义时
-
this 指向的是最后调用它的对象
-
然后划分一下this的场情
-
普通函数调用
-
作为方法来调用
-
作为构造函数来调用
-
使用apply/call方法来调用
-
Function.prototype.bind方法
-
es6箭头函数
普通函数调用:
function say(){
console.log(this);
}
say();// Window
调用say(),打印的this是Window对象。因为say是全局方法,被顶级对象window调用,等价于window.say();
作为对象方法调用:
例1:
let Person = {
say:function(){
console.log(this);
}
};
Person.say();//Person
在 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,在使用这种调用方式时,this 被自然绑定到该对象。
例2:
let Person2 = {
say:function(){
var fun = function(){
console.log(this);
}
fun();
}
};
Person2.say();//Window
函数fun()没有上级对象调用它,所以它内部的this仍然是Window, 这属于 JavaScript 的设计缺陷,正确的设计方式是内部函数的 this 应该绑定到其外层函数对应的对象上,为了解决这个问题一般我们会:
例3
let Person3 = {
say:function(){
var _this = this;
var fun = function(){
console.log(_this);
}
fun();
}
};
Person3.say();//Person3
作为构造函数调用:
function Person4(name){
this.name = name;
console.log(this);
console.log(this.name);
}
let p1 = new Person4('ccued');//p1 ccued
使用new操作符构造出来的对象,this 绑定到新创建的对象上.
JavaScript 支持面向对象式编程,与主流的面向对象式编程语言不同,JavaScript 并没有类(class)的概念,而是使用基于原型(prototype)的继承方式。相应的,JavaScript 中的构造函数也很特殊,如果不使用 new 调用,则和普通函数一样。作为又一项约定俗成的准则,构造函数以大写字母开头,提醒调用者使用正确的方式调用。如果调用正确,this 绑定到新创建的对象上。
使用 apply 或 call 调用:
let cat = {
name:'cat',
say:function(text){
console.log('I am cat:' + text);
console.log(this.name);
}
}
let dog = {
name:'dog'
};
cat.say.call(dog,'haha');// I am cat : haha , dog
apply 和 call 方法允许切换函数执行的上下文环境(context),即 this 绑定的对象。这里我们让“狗”去调“猫”的方法say,因为是“狗”调用的,所以this指向狗
Function.prototype.bind方法:
let cat2 = {
name:'cat',
say:function(text){
console.log('I am cat:' + text);
console.log(this.name);
}
}
let dog2 = {
name:'dog'
};
let func = cat2.say.bind(dog2);
func('hehe');// I am cat:hehe dog
this指向同上,只是bind返回方法,并不立即执行。
通过bind方法绑定后, 函数将被永远绑定在其第一个参数对象上, 而无论其在什么情况下被调用
箭头函数:
let ES6 = {
name:'es6',
say:()=>{
console.log(this);
},
say2:function(){
let func = ()=>{
console.log(this);
};
func();
}
}
ES6.say();//Window
ES6.say2(); // ES6
箭头函数this指向固定化,始终指向外部对象
箭头函数say由ES6这个对象定义,所以this同ES6的this,即Window。
箭头函数func由say2定义,所以this同say2的this,即ES6
箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象
参考文献:
https://www.ibm.com/developerworks/cn/web/1207_wangqf_jsthis/index.html
参与讨论