关于javascript中this的指向

关于javascript中this的指向

我GitHub上的菜鸟仓库地址: 点击跳转查看其余相关文章
文章在个人博客上的地址: 点击跳转

        学习javascript,必不可少的确定要理解this的指向。要学习this指向以前,就要先理解了我前面写的几篇文章,会更容易理解this的指向。javascript

        前面的文章说到, 执行上下文的建立阶段,主要有三个内容:java

        一、建立变量对象;二、初始化做用域链;三、肯定this的指向。git

        前两个内容我都做了详细的解析了,在这里,是时候要说一下第三个内容了,肯定this的指向。其实this的指向从一些理论知识上理解,是很复杂的,看过很多文章都没有说的很清楚,反而说得人懵逼了。其实,this的指向是很是简单的,明确了它的规律,不要被太多代码表达形式的改变而影响了正常的认识思惟,那就能够了。github

        好了,来个广泛例子:函数

//全局环境
var a = 10;
function inner(){
    var a = 20;
    console.log(this.a);
}
inner();

        固然了,打印结果是10,this就是指向全局对象。学习

        好了,该解析this了,咱们都知道this的指向是函数被调用的时候肯定的。this

        简单直接说结论:经过对象访问属性的方式执行函数,this就是指向这个对象,其余状况,严格模式下都是指向undefined,非严格模式下都是指向全局对象。code

        先解析上面例子,上面的inner函数是在全局环境中直接调用的:inner(   ),你们能够理解这个调用,就是这一对方括号(),因此它是指向全局对象,因此this.a就是10。对象

//全局环境
var a = 10;
var example = {
    a : 20,
    b : this.a + 10
}
console.log(example.b);

        打印结果是多少?30吗?错了,不是经过example这个对象访问b属性,因此b里面的this就是指向example吗?错了。ip

        我说的是对象访问属性的方式执行函数,你这个b属性内容不是函数。因为example是在全局环境中声明的,因此里面的this就是指向全局对象,或者说,this的肯定是函数被执行时候肯定的,你的函数呢?往上找,就是全局对象这个大函数了,因此这个this就是指向全局对象。

        固然了,若是你将example放进去某个函数里面,对照一下个人结论,就会知道这个this在严格模式下就会指向undefined,非严格模式就是指向全局对象。例子以下:

//非严格模式下的全局环境
var a = 10;
function outer(){
    var example = {
        a : 20,
        b : this.a + 10
    }
    return example.b;
}
outer();//打印结果为20
//严格模式下的全局环境
'use strict'
var a = 10;
function outer(){
    var example = {
        a : 20,
        b : this.a + 10
    }
    return example.b;
}
outer();//执行会报错,由于this指向undefined

        还问为何?由于outer函数被执行时候这个this才肯定啊,而outer这个函数是单独调用啊,直接outer(  )这样调用啊,因此就是结论中那样啊。

        好了,那怎样是属于对象访问属性的方式执行函数呢?再来例子:

//全局环境
var a = 10;
var example = {
    a : 20,
    b : function(){
        return this.a;
    }
}
console.log(example.b());

        好了,此次打印结果是20了,由于经过了example访问b属性方式执行函数的,经过这个一点运算符的属性访问方式,叫作成员访问。稍微改改再来例子:

//全局环境
var a = 10;
var example = {
    a : 20,
    b : function(){
        return this.a;
    }
}
var c = example.b;
console.log(c());

        仍是20吗?不是了,非严格模式是10,严格模式报错(后面都是非严格模式的例子),由于调用函数c,前面只是经过example.b将函数的地址传给了c而已,你调用函数时候,仍是单独调用啊。开始懂了对不对,再来例子:

//全局环境
var a = 10;
function runAway(){
    return this.a;
}
var example = {
    a : 20,
    b : runAway
}
console.log(example.b());

        若是你不假思索就能说是20的话,证实你已迈出了一大步了,同一个道理,是经过对象访问属性的方式执行函数的,我管你的b属性是直接指向函数,仍是经过函数声明指向函数的,反正你的this就是指向对象example。

        好了,结合上面的再改一改例子:

//全局环境
var a = 10;
function runAway(){
    return this.a;
}

function worker(fn){
    fn();
}
var example = {
    a : 20,
    b : runAway
}
worker(example.b);

        可能你会说,经过example.b这样的的方式,我无论你有没有跳出来的runAway,this确定是指向example啦,那就要重温一下个人结论了,我说的是经过对象访问属性的方式执行函数,你执行了吗,你有一对方括号吗?可能你会说,他们传入去worker函数,里面就会加一对方括号执行啊,那就错了。

        经过这种方式的执行函数,其实已经变味了,这种状况和上面的例子:var c = example.b,而后c( )执行函数式同样的,你只不过经过example.b将这个函数地址传入了worker函数,而后执行而已。

        因此上面这个例子,就是结论中的其余状况咯,严格模式this指向undefined(固然这个例子会报错,由于undefined没有a属性),非严格模式指向全局对象(固然这个例子会打印undefined,由于全局对象没有b属性)。

        好了,最后再举一下其余例子:

//全局环境
var a = 10;
var example = {
    a : 20,
    b : function(){
        return this.a;
    }
}
//例子一
console.log(example.b()); //打印结果为20
//例子二
console.log((example.b)()); //打印结果为20
//例子三
console.log((false || example.b)()); //打印结果为10

        好了,在例子一中,很清楚明白就是常规的this指向了example。

        例子二中,你加了一个括号也没用啊,我没有将它的函数地址赋值其余什么变量啊,因此和例子一也是同样的。

        至于例子三,咱们能够这样理解,你在括号里面进行了一些其余运算,因此经过example.b这个方式只是拿了函数地址出来运算,因此在例子三中,括号的结果是example.b这个结果,因此是拿到了一个函数的地址,最后调用的时候仍是单独调用啊,就相似前面例子的worker函数那样啊。

        网上还有不少像例子三那样的古灵精怪的例子,其实很简单,你运算过了,最后出来的东西再加方括号调用,就是单独调用了。

        最后,好像忘了个很经常使用的构造函数的this指向:

//先来个构造函数Mankind
function Mankind(name){
    this.name = name;
}
//实例化对象Dad
var Dad = new Mankind('BaBa');
console.log(Dad.name); //打印结果为BaBa

        很明白了,经过构造函数实例化对象,构造函数里面的this就是指向这个实例化对象了。

相关文章
相关标签/搜索