1

this关键词
概述
this是什么
this关键字是JavaScript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在所有函数的作用域中。但是即使在非常有经验的JavaScript开发者也很难说清它到底指向什么。
世界上,JavaScript中this 的机制并没有那么先进,但是开发者往往会把理解过程复杂化。毫不夸张地说,不理解它的含义,大部分开发任务都无法完成。
this都有一个共同点,他总是返回一个对象。简单说,this就是属性或方法‘当前’所在的对象。
var = person ={
name :'张三',
describe:function(){
return'姓名'+this.name;}
};
person.descibe();//'姓名:张三'

为什么要使用this
this提供了一种更优雅的方式来隐式‘传递’一个对象引用,因此可以将API设计的更加简介并且易于复用。
随着你的使用模式越来越复杂,显示传递上下文对象会让代码变得越来越混乱,使用this则不会这样。
function indetify() {return this.name.toUpperCase();}
function speak(){ console.log('Hello, i'm'+identify.call(this)); }
var me ={name :'Kyle'};
var you ={name:'Reader'};
identify.call(me);//KYLE
identify.call(you);//READER
speak.call(me);//Hello,我是KYLE
speak.call(you);//Hello,我式READER

调用位置
想要了解this的绑定过程,首先要理解调用位置:调用位置就是函数在代码中被调用的位置(而不是声明的位置)。
通常来说,寻找调用位置就是寻找“函数被调用的位置”。最重要的式要分析调用栈(就是为了到达当前执行位置调用的所有函数)。
function baz(){
//当前调用栈式:baz。因此,当前调用位置式全局作用域
console.log('baz');
bar();//<--bar的调用位置
}
function bar (){82
//当前调用栈式baz-> bar。因此,当前调用位置在baa中sonsole.log('bar');
}
baz();//<--baz的调用位置

绑定规则
默认绑定
在一个函数体中使用this,当该函数被独立调用。可以把这条规则看作式无法应用 其他规则时的默认规则。
function foo(){
console.log(this,a);
}
var a =2
foo();//2
声明在全局作用域中的变量(比如 var a=2)就是全局对象的一个同名属性。当调用foo()函数时,
this a 被解析成了全局变量a。
函数调用时应用了this 的默认绑定,因此this指向全局对象。

隐式绑定
隐式绑定的规则需要考虑的式调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含。当然,这种说法并不准确。
function foo(){
console.log(this.a);}
var obj = {a:2,
foo:foo};
obj.foo()//2
调用位置会使用ovj上下文来引用函数,因此你可以说函数被调用时obj对象‘’拥有或者 ‘包含’它。
隐式绑定
隐式丢失式最常见的this 绑定问题,指的就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象。
function foo(){
console.log(this.a);}
var obj ={a:2,
foo:foo};
var bar = obj.foo;函数别名
var a ='Opps,global';//a式全局对象属性
bar();//'oops,global'
bar式obj.foo的一个引用,但是实际上,他引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰符的函数调用,因此应用了默认绑定。

显示绑定
显示绑定就是确定在调用时,this所绑定的对象。JavaScript中提供了apply()方法和call方法实现,
这两个方法的第一个参数接受一个对象,会把这个对象绑定到this,接着在调用函数是指定这个this。
function foo(){
console.log(this.a);}
var obj ={a:2};
foo.call(obj);//2
如果传入了一个原始值来当作this 的绑定对象,这个原始值会被转换成它的对象形式,这通常被称之为'装箱'。

new绑定
在JavaScript中,构造函数只是一些使用new操作符时被调用的函数。包括内置对象函数在内的所有函数都可用new函数,会自动执行下面的操作:
1创建(或者说构造)一个全安行的对象。
2这个新对象会绑定到函数调用的this。
3如果函数没有返回其他对像,那么new表达式中的函数调用会自动返回这个新对象。
function foo (a){
this.a = a;}
var bar = new foo(2);
console.log(bar.a);//2

绑定例外
被忽略的this
如果把null或者undefined作为this 的绑定对象的传入call ,apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。
function foo(){
console.log(this.a);}
var a = 2;
foo.call (null);//2
间接引用
有可能(有意或者无意的)创建一个函数的'间接引用',在着中情况下,调用这个函数会应用默认绑定规则。
间接引用最容易在赋值时放生:
function foo(){
console.log(this.a);}
var a =2;
var 0 = {a:3,
foo:foo};
var p = {a:4};
o.foo();//3
(p,foo = o.foo)();//2

注意事项
避免多层this
多层函数或方法嵌套可能导致不同层次的this绑定的对象不同,如下示代码所示:
var 0 = {
f1:function (){
console.log(this);
var f2 = function(){
console.log(this);}
();}}o.f1();
上面代码包含两层this,结果运行后,第一层指向对象o,第二层指向全局对象。

避免数组方法中的this
数组的map和foreach方法,允许提供一个函数作为参数。这个函数内部不应该使用this。
var o = {
v:'hello',
p:['a1','a2'],
f:function f(){
this.p.forEach(function(idem){
console.log(this.v+''+item);}) }}
o.f();
上面代码中,foreach方法的回调函数中的this,其实是指向全局对象,因此取不到o.v的值。

避免回电函数中的this 回调函数中的this 经常会改变绑定的对象,最好的解决方案就是避免这样使用this。
Var 0 ={
name :'卧龙学院'}
o.fn = function(){
console.log (this.name);}
var name = '前端开发';
function f(v){
v();}f(o.fn);
上面的代码中,f()方法的回调函数中this ,其实是指向全局对象。


李通
15 声望5 粉丝

下一篇 »
初识DOM