this是对象,是在运行时基于函数
的执行环境
(和对象有关)绑定的,首先,当代码没执行前,或没执行到之前,this 是没有指向的,所以
切记:在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了
。因为this的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。
this只要一出现,一定牵扯到函数和对象
一般方法:首先分析this所在的函数是被当做哪个对象的方法调用的,则该对象就是this所引用的对象。
其实,this的取值,分五种情况。我们来挨个看一下。
在全局环境下,this永远是window,这个应该没有非议。
123 | console.log(this==window);//turethis.a=20;console.log(window.a); |
---|
普通函数在调用时,其中的this也都是window。
1234567 | var home="中国";var person=function(){ var home="河南" console.log(this); //window console.log(this.home); //中国 }person(); |
---|
但是严格模式下 this是undefined(竞然):
12345678910 | function person1(){ return this; }person1()===window; //truefunction person2(){ "use strict" //严格模式 return this;}person2()===undefined; //true |
---|
所谓构造函数就是用来new对象的函数。其实严格来说,所有的函数都可以new一个对象,但是有些函数的定义是为了new一个对象,而有些函数则不是。另外注意,构造函数的函数名第一个字母大写(规则约定)。例如:Object、Array、Function等。
如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象
1234567891011121314 | window.home="中国";window.age="5000+";function Person(){ this.home="河南"; this.age=20; console.log(this); //Person {home: "河南", age: 20} console.log(this.home);// 河南}var chongqing = new Person();console.log(chongqing.home); //河南还是中国console.log(chongqing.age); //20还是5000+console.log(age); //5000+还是20 |
---|
以上代码中,如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象,即上文中的chongqing。
上个例子中构造函数没有返回值,默认返回this,但是若有返回语句,返回一个对象的话,会将return的对象作为返回值
12345678910111213 | function Myclass(){ this.a=20;}var o=new Myclass();console.log(o.a); //20function Person(){ this.a=20; return { a: 21};}var o=new Person();console.log(o.a); //21还是20 |
---|
注意,以上仅限new Person()的情况,即Person函数作为构造函数的情况。
如果直接调用Person函数,而不是new Person(),情况就大不一样了。相当于普通函数
1234567891011 | window.home="中国";window.age="5000+";function Person(){ this.home="河南"; this.age=20; console.log(this); //window 还是Person {home: "河南", age: 20} console.log(this.home);//???河南还是中国 console.log(home);//???河南还是中国}Person(); |
---|
这种情况下this是window,就是相当于普通函数中的this
构造函数还有一种情况,在构造函数的prototype中,this代表着什么?
在整个原型链中,this代表的是当前对象的值
1234567891011121314 | window.home="中国";window.age="5000+";function Person(){ this.home="河南"; this.age=20; console.log(this); //Person {home: "河南", age: 20}}Person.prototype.getHome=function(){ console.log(this.home); //河南}var chongqing= new Person();chongqing.getHome();// |
---|
如上代码,在Person.prototype.getHome函数中,this指向的是chongqing对象。因此可以通过this.name获取chongqing.name的值。
其实,不仅仅是构造函数的prototype,即便是在整个原型链中,this代表的也都是当前对象的值。
在这又分两种情况:
被调用
,此时函数中的this指向该对象
被赋值
到了另一个变量中,this的值是window
###1. 如果函数作为对象的一个方法时,并且作为对象的一个方法被调用
时,函数中的this指向该对象
。
1234567891011 | window.home="中国";window.age="5000+";var obj={ home:"河南", person: function(){ console.log(this); //Object {home: "河南"} console.log(this.home); //河南 }};obj.person(); |
---|
以上代码中,person不仅作为一个对象的一个方法,而且的确是作为对象的一个方法被调用。结果this就是obj对象
。
注意
,如果person函数不作为obj的一个方法被调用
,会是什么结果呢?
如果person函数被赋值到了另一个变量中,并没有作为obj的一个方法被调用,那么this的值就是window
1234567891011 | window.home="中国";window.age="5000+";var obj={ home:"河南", person: function(){ console.log(this); //??window还是object console.log(this.home); //??中国还是河南 }};var person1=obj.person;person1(); |
---|
如上代码,如果person函数被赋值到了另一个变量中,并没有作为obj的一个属性被调用,那么this的值就是window,相当于全局了,this.home的值为中国
在ES3中,此时使用this比较糟糕,因为this失去了方向,引用的是window对象,而不是定义函数所在的对象,欣慰的是,this在ES5中是固定的,我们应该清楚地了解这种情况
注意: 在ES3中,当函数作为某个对象的方法调用时,this等于那个对象,不过在闭包中,匿名函数的执行环境具有全局性,此时通常this指向window
1234567891011 | var obj={ home:"河南", person: function(){ function person1(){ console.log(this); //window console.log(this.home); //undefined } person1();}};obj.person(); |
---|
总结:当this值的宿主环境被封装在另一个函数内部或在另一个函数的上下文被调用时,this将永远是对window对象的引用(再次说明,this在ES5中是固定的)
如何改变上述情况呢?
可以在父函数中使用作用域链来保留对this的引用,以使this值不丢失
。如下代码演示了如何使用that变量及其作用域来有效跟踪函数上下文
12345678910111213 | var obj={ home:"河南", person: function(){ var that=this; //person作用域中,保存this引用对象obj(而不是window) function person1(){ //输出通过作用域得到河南,因为that=this console.log(that); //Object {home: "河南"} console.log(that.home); //河南 } person1();}};obj.person(); |
---|
先简单说一下call和apply和bind如何使用
特定的作用域中调用函数
,,都有两个参数call/apply(作用域
,传递给函数的参数
)this指的就是这第一个参数
。
牢记:当一个函数被call或apply或bind调用时,this的值就取传入的对象的值,即call()或apply或bind()括号里的对象
。
call实例
12345678910 | window.home="中国";window.age="5000+";var obj={ home:"河南"};var person=function(){ console.log(this); //Object {home: "河南"} console.log(this.home); //河南 }person.call(obj); |
---|
还要注意:apply()的
参数
为空时,默认调用全局对象。
123456789 | var x = 0; function test(){ alert(this.x); } var o={}; o.x = 1; o.m = test; o.m.apply(); //0 |
---|
bind()实例
12345678 | window.color="red";var o={color:"blue"};function sayColor(){ alert(this.color);}var objectSayColor=sayColor.bind(o);objectSayColor(); //blue还是red |
---|
sayColor()调用bind()并传入对象o。创建了objectSaycolor()函数,objectSaycolor()函数中的this的值等于o,因此,即使是在全局作用域中调用这个函数也会看到“blue”。
12345 | var one = document.getElementByIdx( 'one' );one.onclick = function(){ alert( this.innerHTML ); //this指向的是one元素, |
---|
友情链接: Javascript高级程序设计(第3版)-关于this对象-182页 JavaScript启示录-this部分 博客-深入理解Js-this 博客-js中this 慕课网Javascript深入浅出-this部分 博客-this关键字详解