JavaScript中的this

先记住两句话:

  1. this 的指向在执行时决定,而不是定义时

  2. this 指向的是最后调用它的对象

  3.  

然后划分一下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

https://github.com/moshanghan/fe-chuishui/blob/master/javascript/%E4%BD%9C%E7%94%A8%E5%9F%9F/%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8Cthis.md

2019-05-16 11:21:36 1858 0

参与讨论

选择你的头像