This 关键字
重要的事情说三遍:
注:This指向哪个对象不取决于函数定义的位置,而取决于调用的位置
注:This指向哪个对象不取决于函数定义的位置,而取决于调用的位置
注:This指向哪个对象不取决于函数定义的位置,而取决于调用的位置
this关键字是JavaScript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在所有函数的作用域中。但是即使是非常有经验的JavaScript开发者也很难说清它到底指向什么。
实际上,JavaScript中this的机制并没有那么先进,但是开发者往往会把理解过程复杂化。毫不夸张地说,不理解它的含义,大部分开发任务都无法完成。
this都有一个共同点,它总是返回一个对象。简单说,this就是属性或方法“当前”所在的对象。
This的基本用法一:
//定义一个全局变量v var v= 100; // this经常被定义在函数的作用域中 function fn() { // this总是要返回一个对象 console.log(this.v); //this 指向哪个对象,不取决于函数定义的位置。 } // this 指向哪个对象,取决于调用的位置 fn();//函数的调用
解析如下:
This的基本用法二:
//定义一个全局变量v var v= 100; // this经常被定义在函数的作用域中 function fn() { // this总是要返回一个对象 console.log(this.v); //this 指向哪个对象,不取决于函数定义的位置。 } // 定义一个对象,将fn函数作为obj对象的方法 var obj = { v:200, f:fn } obj.f();//200
解析图如下:
下面介绍this绑定的四种方式
1、默认绑定
在一个函数体中使用this,当该函数被独立调用。可以把这条规则看作是无法应用,其他规则时的默认规则。
function foo(){ console.log(this.a); } var a = 2 ; foo();//2
声明在全局作用域中的变量(比如var a = 2)就是全局对象的一个同名属性。当调用foo()函数时,this.a被解析成了全局变量a。
函数调用时应用了this的默认绑定,因此this指向全局对象。
2、隐式绑定
隐式绑定的规则 需要考虑的是调用位置是否有上下文对象,或者说是否某被某个对象拥有或者包含。这种说法并不准确。
function fn() { console.log(this.a); } var obj = { a : 19, fn :fn } obj.fn()
调用位置会使用obj上下文来引用函数,因此你可以说函数被调用时obj对象‘拥有’或者‘包含’它。
隐式丢失是最常见的this绑定问题,指的就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象。
// 定义一个全局变量 var v = 100; // 定义一个函数 function fn() { console.log(this.v); } // 定义一个对象 var obj = { v:200, f : fn//对象obj的f()方法指向fn()函数 } // 定义一个全局变量,并被赋值为对象obj的f()方法 var fun = obj.f; // 将fun作为一个函数进行调用 fun();
3、显示绑定
显示绑定就是明确在调用时,this所绑定的对象。JavaScript中提供了apply()方法和call()方法实现,这两个方法的第一个参数接收是一个对象,会把这个对象绑定到this,接着在调用函数时指定这个this。
// 定义一个全局变量 var v = 100; // 定义一个函数 function fn() { console.log(this.v); } // 定义一个对象 var obj = { v:200, f : fn//对象obj的f()方法指向fn()函数 } // 定义一个全局变量,并被赋值为对象obj的f()方法 var fun = obj.f; // 将fun作为一个函数,使用apply()方法将obj传参进去,进行调用。 fun.apply(obj);//200
4、new绑定
在JavaScript中,构造函数只是一些使用new操作符时被调用的函数。包括内置对象函数在内的所有函数都可以用new来调用,这种函数调用称为构造函数调用。
function Hero(name){ this.name = name; } // this取决于函数调用的位置 var hero1 = new Hero('猪猪侠'); var hero2 = new Hero('超人强'); console.log(hero1,hero2); //输出结果:Hero { name: '猪猪侠' } Hero { name: '超人强' }
this 的练习——实现继承
记住一句话:This指向哪个对象不取决于函数定义的位置,而取决于调用的位置。
function Hero1() { this.name = '猪猪侠'; this.sayMe = function () { console.log(this.name); } } function Hero2(){ Hero1.call(this);//继承Hero1的属性和方法 this.age = 20; this.sayMe = function () { console.log('我叫'+this.name+',今年'+this.age); } } //构造函数方式创建hero对象 var hero = new Hero2(); hero.sayMe();//我叫猪猪侠,今年20 var obj = { name:'迷糊老师', age:80, sayMe : hero.sayMe } obj.sayMe();//我叫迷糊老师,今年80 // obj.sayMe()调用obj对象的sayMe方法,调用位置在obj对象中, // 所以输出obj对象的name属性和age属性。