The content of this article is about the usage of this keyword in JavaScript (with code). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
This article mainly explains the pointing problem of this keyword in JS (in the browser environment).
First of all, we must understand the several ways to call functions in JS:
Ordinary function calls
Call as a method
Call as a constructor
Use the apply/call method to call the
Function.prototype.bind method
es6 Arrow Function
#But no matter which method the function is called, please remember one thing: Who When this function or method is called, the this keyword points to whom.
Next, we will discuss these different situations according to the situation:
function person(){ this.name="xl"; console.log(this); console.log(this.name); } person(); //输出 window xl
In this code, the person
function is called as a normal function. In fact, person
is used as a method of the global object window
The call is made, that is, window.person()
;
So this is where the window
object calls the person
method, then person
in the function this
refers to window,
At the same time, window
also has another attribute name
, value For xl
.
var name="xl"; function person(){ console.log(this.name); } person(); //输出 xl
the same place person
is called as a method of window
, at the beginning of the code A global variable name is defined, the
value is xl,
it is equivalent to an attribute of window
, that is, window.name="xl",
And because this
points to window
when calling person
, so xl
.## will be output here.
In the above code, the call of the ordinary function is called as the method of the window object . Obviously the
this keyword points to the
window object.
Let’s look at other forms
var name="XL"; var person={ name:"xl", showName:function(){ console.log(this.name); } } person.showName(); //输出 xl //这里是person对象调用showName方法,很显然this关键字是指向person对象的,所以会输出name var showNameA=person.showName; showNameA(); //输出 XL //这里将person.showName方法赋给showNameA变量,此时showNameA变量相当于window对象的一个属性,因此showNameA()执行的时候相当于window.showNameA(),即window对象调用showNameA这个方法,所以this关键字指向window
And another form:
var personA={ name:"xl", showName:function(){ console.log(this.name); } } var personB={ name:"XL", sayName:personA.showName } personB.sayName(); //输出 XL //虽然showName方法是在personA这个对象中定义,但是调用的时候却是在personB这个对象中调用,因此this对象指向personB
function Person(name){ this.name=name; } var personA=Person("xl"); console.log(personA.name); // 输出 undefined console.log(window.name);//输出 xl //上面代码没有进行new操作,相当于window对象调用Person("xl")方法,那么this指向window对象,并进行赋值操作window.name="xl". var personB=new Person("xl"); console.log(personB.name);// 输出 xl //这部分代码的解释见下
//下面这段代码模拟了new操作符(实例化对象)的内部过程 function person(name){ var o={};//创建空对象 o.__proto__=Person.prototype; //为创建对象指定原型,继承原型属性和方法 Person.call(o,name); return o; } var personB=person("xl"); console.log(personB.name); // 输出 xl
这段代码涉及到了_proto_及prototype的概念,如果有需要了解,请点击链接
在person
里面首先创建一个空对象o,将o的proto指向Person.prototype完成对原型的属性和方法的继承
Person.call(o,name)
这里即函数Person
作为apply/call
调用(具体内容下方),将Person
对象里的this
改为o,即完成了o.name=name
操作
返回对象o。
因此`person("xl")`返回了一个继承了`Person.prototype`对象上的属性和方法,以及拥有`name`属性为"xl"的对象,并将它赋给变量`personB`. 所以`console.log(personB.name)`会输出"xl"
在JS里函数也是对象,因此函数也有方法。从Function.prototype上继承到Function.prototype.call/Function.prototype.apply
方法call/apply
方法最大的作用就是能改变this
关键字的指向。
Obj.method.apply(AnotherObj,arguments);
var name="XL"; var Person={ name:"xl", showName:function(){ console.log(this.name); } } Person.showName.call(); //输出 "XL" //这里call方法里面的第一个参数为空,默认指向window。 //虽然showName方法定义在Person对象里面,但是使用call方法后,将showName方法里面的this指向了window。因此最后会输出"XL"; funtion FruitA(n1,n2){ this.n1=n1; this.n2=n2; this.change=function(x,y){ this.n1=x; this.n2=y; } } var fruitA=new FruitA("cheery","banana"); var FruitB={ n1:"apple", n2:"orange" }; fruitA.change.call(FruitB,"pear","peach"); console.log(FruitB.n1); //输出 pear console.log(FruitB.n2);// 输出 peach
FruitB
调用fruitA
的change
方法,将fruitA
中的this
绑定到对象FruitB
上。
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() //输出 “my name is XL”; //这里的setTimeout()定时函数,相当于window.setTimeout(),由window这个全局对象对调用,因此this的指向为window,则this.name则为XL
那么如何才能输出"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) //注意这个地方使用的bind()方法,绑定setTimeout里面的匿名函数的this一直指向Person对象 } } var person=new Person("xl"); person.sayName(); //输出 “my name is xl”;
这里setTimeout(function(){console.log(this.name)}.bind(this),50);
匿名函数使用bind(this)
方法后创建了新的函数,这个新的函数不管在什么地方执行,this
都指向的Person
,而非window,
因此最后的输出为"my name is xl"而不是"my name is XL"
另外几个需要注意的地方:setTimeout/setInterval/匿名函数执行
的时候,this
默认指向window对象
,除非手动改变this的指向。在《javascript高级程序设计》当中,写到:“超时调用的代码(setTimeout
)都是在全局作用域中执行的,因此函数中的this的值,在非严格模式下是指向window对象,在严格模式下是指向undefined”。本文都是在非严格模式下的情况。
var name="XL"; function Person(){ this.name="xl"; this.showName=function(){ console.log(this.name); } setTimeout(this.showName,50); } var person=new Person(); //输出 "XL" //在setTimeout(this.showName,50)语句中,会延时执行this.showName方法 //this.showName方法即构造函数Person()里面定义的方法。50ms后,执行this.showName方法,this.showName里面的this此时便指向了window对象。则会输出"XL";
var name="XL"; function Person(){ this.name="xl"; var that=this; this.showName=function(){ console.log(that.name); } setTimeout(this.showName,50) } var person=new Person(); //输出 "xl" 13 //这里在Person函数当中将this赋值给that,即让that保存Person对象,因此在setTimeout(this.showName,50)执行过程当中,console.log(that.name)即会输出Person对象的属性"xl"
var name="XL"; var person={ name:"xl", showName:function(){ console.log(this.name); } sayName:function(){ (function(callback){ callback(); })(this.showName) } } person.sayName(); //输出 XL var name="XL"; var person={ name:"xl", showName:function(){ console.log(this.name); } sayName:function(){ var that=this; (function(callback){ callback(); })(that.showName) } } person.sayName() ; //输出 "xl" //匿名函数的执行同样在默认情况下this是指向window的,除非手动改变this的绑定对象
eval函数执行的时候,this绑定到当前作用域的对象上。
var name="XL"; var person={ name:"xl", showName:function(){ eval("console.log(this.name)"); } } person.showName(); //输出 "xl" var a=person.showName; a(); //输出 "XL"
es6
里面this
指向固定化,始终指向外部对象,因为箭头函数没有this,
因此它自身不能进行new
实例化,同时也不能使用call, apply, bind
等方法来改变this
的指向。
function Timer() { this.seconds = 0; setInterval( () => this.seconds ++, 1000); } var timer = new Timer(); setTimeout( () => console.log(timer.seconds), 3100); // 3 // 在构造函数内部的setInterval()内的回调函数,this始终指向实例化的对象,并获取实例化对象的seconds的属性,每1s这个属性的值都会增加1。否则最后在3s后执行setTimeOut()函数执行后输出的是0
相关文章推荐:
The above is the detailed content of Usage of this keyword in javascript (with code). For more information, please follow other related articles on the PHP Chinese website!