· 普通函数调用
· 作为方法来调用
· 作为构造函数来调用
· 使用apply / call 方法来调用
· Function.prototype.bind方法
· ES6 箭头函数
不管函数是按哪种方法来调用,谁调用这个函数或方法,this关键字就指向谁。
· 普通函数调用:
eg①:
function person(){ this.name="xl"; console.log(this); console.log(this.name); } person(); // output => window xl
【解析】: 在这段代码中person函数作为普通函数调用,实际上person是作为全局对象window的一个方法来进行调用的,即 window.person();
所以这个window对象调用了person方法,那么person函数当中的this即指window,同时window还拥有用另外一个属性name,值为xl。
eg②:
var name="xl"; function person(){ console.log(this.name); } person(); // output => xl
【解析】: 这里的person作为window的方法来调用。在代码的开始定义了一个全局变量name,值为xl。它相当于window的一个属性,即:window.name = “xl”,在调用person的时候this指向window。因此这里会输出xl。
· 作为方法来调用
eg①:
var name="XL"; var person = {
name: "xl",
showName: function(){
console.log(this.name)
}
}
person.showName(); // output => xl
【解析】: person对象调用showName方法,很显然this关键字是指向person对象的,所以会输出xl。
eg②:
var name="XL"; var person = {
name: "xl",
showName: function(){
console.log(this.name)
}
}
var showNameA = person.showName;
showNameA(); // output => XL
【解析】:这里将person.showName方法赋予showNameA变量。此时showNameA变量相当于window对象的一个属性。因此showName()执行的时候相当window.showNameA(),即window对象调用showNameA这个方法,所以this关键字指向window。
eg③:
var personA = { name: "xl", showName: function() { console.log(this.name); } } var personB = { name: "XL", sayName: personA.showName } personB.sayName(); // output => XL
【解析】:虽然showName方法是在personA这个对象中定义,但是调用的时候却是在personB这个对象调用,因此this对象指向personB。
· 作为构造函数来调用
function Person(name){ this.name=name; } var personA = Person("xl"); console.log(personA.name); // output => undefined console.log(window.name); // output => xl
【解析】:上述代码没有进行new操作(没有实例化,相当于这个函数给了一个全局变量),相当于window对象调用Person(‘xl‘)方法。那么,并进行赋值操作window.name=“xl”。
· 使用apply / call 方法来调用
在js里函数也是对象,因此函数也有方法。从Function.proytotype上继承到Function.prototype.call/Function.prototype.apply方法。
call/apply方法最大的作用就是能改变this关键字的指向。
Obj.method.apply(AnotherObj, arguments);
var name = "WL"; var Person = { name: "xl", showName: function() { console.log(this.name); } } Person.showName.call();
// call 方法后面的括号中的替换对象如果为空指代就是“window”。
【解析】:这个call方法里面的第一个参数为空,默认指向window。
虽然showName方法定义在Person对象里面,但是使用call方法后,将showName方法里面的this指向window。因此会输出“WL”。
当showName方法给到了window后,肯定是window执行这个方法,所以this的指向就是window。
· Function.prototype.bind()
var name="XL"; function Person(name){ this.name=name; this.sayName=function(){ setTimeout(function(){ console.log("my name is "+this.name); },50) } } var person=new Person("xl"); person.sayName();
【解析】:这里的setTimeout()定时函数,相当于window.setTimeout(),由window这个全局对象调用。因此this指向为window,则this.name则为XL。
setTimeout() 的默认指向是window。
怎样才能输出"my name is xl"呢?
var name="XL"; function Person(name){ this.name=name; this.sayName=function(){ setTimeout(function(){ console.log("my name is "+this.name); }.bind(this),50) } } var person=new Person("xl"); person.sayName(); // output => "my name is xl"
【解析】:这里setTimeout函数,匿名函数使用bind(this)方法后创建了新的函数,这个新的函数不管在什么地方执行,this都指向Person,而非window,因此最后的输出都为“my name is xl”,而不是“my name is WL”。
setTimeout()/ setInterval() / 匿名函数 执行的时候,this默认指向window。除非手动改变this的指向。【因为bind绑定了person函数,所以不管在哪儿引用这个方法,this的指向都是person。
怎样才能输出"my name is WL"?
var name = "WL"; function Person() { this.name = "xl"; this.showName = function () { · console.log(this.name); } setTimeout(this.showName, 50); } var person = new Person();
另一种输出"my name is xl"?
function Person() { this.name = "xl"; var that = this; this.showName = function () { console.log(that.name); } setTimeout(this.showName, 50) } var person = new Person();
· ES6 箭头函数
var x = 11; var obb = { x: 222, y: { x:333, obc: function f() { console.log(this) var x = 111; var obj = { x: 22, say: () => { console.log(this.x); } } obj.say() } } } obb.y.obc()
【解析】:输出结果是333。
原因箭头函数没有this,剪头函数的this是继承父执行上下文里面的this ,这里箭头函数的执行上下文是函数f(),所以它就继承了f()的this,
原文:https://www.cnblogs.com/Shouxi/p/11977873.html