资讯专栏INFORMATION COLUMN

一段关于JS中this应用奇葩代码引发的思考

AlanKeene / 2955人阅读

摘要:,对外公开的接口。更需要注意立即执行函数,返回的是一个匿名函数,也是一个闭包,在这里一定要注意一个问题是在进入可执行上下文时创建的。三在方法中,注意如下代码省略代码的实际参数是一个自执行匿名函数,这个匿名函数接受了两个参数,但只返回了。

function DemoFunction(){
    this.init = function(){
        var func = (function(va){
        this.va = va;
        return function(){
            va += this.va;
            return va;
        }
        })(function(va1, va2){
            var va3 = va1 + va2;
            return va1;
        }(1,2));
        
        console.log(func(20));

        this.func = func;
        console.log(this.func(100));
    }
}
var a = new DemoFunction();
a.init();

首先我们得有如下几个概念:

执行上下文:每次当控制器转到ECMAScript可执行代码时,即会进入一个可执行上下文,参考文献:深入理解JavaScript系列(11):执行上下文(Execution Contexts)

this:this的创建是在 “进入执行上下文” 时创建的,在代码执行过程中是不可变的,参考文献:深入理解JavaScript系列(13):This? Yes,this!

自执行函数:准确来说应该叫:立即调用函数表达式。因为他声明后即执行,参考文献:深入理解JavaScript系列(4):立即调用的函数表达式

详细解释此段代码

一、首先看DemoFunction的构造函数

这是代码的重点,第一层代码可以缩减为如下:

function DemoFunction(){
    this.init = function(){
        //省略代码....
    }
}

表示为DemoFunction的实例提供init方法(声明:此处有误导成份,方法应尽可能放在原型链接上,也就是prototype上。),对外公开的接口。

二、在init方法中,再次省略代码如下:
var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(/*省略代码...*/);

//省略代码....

上面代码介绍:

首先定义了一个立即执行函数,并把此函数的执行结果赋值给func。

需要注意立即执行函数中this.va=va这行代码,由于立即执行函数没有调用者,所以在进入可执行上下文时,this会被赋值为Global(浏览器中为window对象)。

更需要注意立即执行函数,返回的是一个匿名函数,也是一个闭包,在这里一定要注意一个问题:this是在进入可执行上下文时创建的。

三、在init方法中,注意如下代码:
var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
})(function(va1, va2){
    var va3 = va1 + va2;
    return va1;
}(1,2));
//省略代码....

va的实际参数是一个自执行匿名函数,这个匿名函数接受了两个参数va1,va2,但只返回了va1。以此为据,那么可以确定va的值也就为1。接着就执行this.va=va这句代码,由于当前this为window,所以参数va的值被赋值到了window的一个叫va的属性上。

四、在init方法中,加上输出语句:
var func = (function(va){
    this.va = va;
    return function(){
        va += this.va;
        return va;
    }
    })(function(va1, va2){
        var va3 = va1 + va2;
        return va1;
    }(1,2));
    
    console.log(func(20));

    this.func = func;
    console.log(this.func(100));
}

结果分析:

第一个console.log输出的是func(20),这里一定要注意调用者是没有具体指定的,此时默认的就是Global(也就是widnow对象),因此输出为:2

第二个console.log输出的是this.func(100),可以看到this.func与func是指向同一个函数的引用,但此时的调用者则指定为this,也就是当前对象的实例,因此输出为:NaN。原因:this(当前对象的实例)作为调用者,在func的函数中va += this.va这句代码中的this是指向当前对象的实例,但当前对象的实例上是没有va属性的。但是va是有值的,当前值为2了。是因为闭包把va值存到内存中了。那么如何让第二次得到的值也是2呢,结果很简单,如下:

    function DemoFunction(){
        this.va = 0;
        this.init = function(){
            var func = (function(va){
            this.va = va;
            return function(){
                va += this.va;
                return va;
            }
            })(function(va1, va2){
                var va3 = va1 + va2; 
                return va1;
            }(1,2));
            console.log(func(20));
            
            this.func = func;
           
            console.log(this.func(100));
        }
    }
    var a = new DemoFunction();
    a.init();

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89849.html

相关文章

  • 批量修改谷歌浏览器(Chrome)地址栏保存历史记录及导出功能探索研究

    摘要:内网调整引发的历史记录修改及的学习由于经常变动导致本地项目的那些存在地址栏的历史记录就都失效了突然脑洞大开有没有办法修改本地历史记录的方法想法是假设我原是新是我历史记录有我通过某种办法强行修改历史记录将替换成这样下次在地址栏输入他就能自动填 内网IP调整引发的Chrome历史记录修改及ShadowRoot的学习 由于IP经常变动, 导致本地项目的那些存在地址栏的历史记录就都失效了, 突...

    JeOam 评论0 收藏0
  • 批量修改谷歌浏览器(Chrome)地址栏保存历史记录及导出功能探索研究

    摘要:内网调整引发的历史记录修改及的学习由于经常变动导致本地项目的那些存在地址栏的历史记录就都失效了突然脑洞大开有没有办法修改本地历史记录的方法想法是假设我原是新是我历史记录有我通过某种办法强行修改历史记录将替换成这样下次在地址栏输入他就能自动填 内网IP调整引发的Chrome历史记录修改及ShadowRoot的学习 由于IP经常变动, 导致本地项目的那些存在地址栏的历史记录就都失效了, 突...

    UsherChen 评论0 收藏0
  • 一个removeEventListener引发思考

    摘要:而为对象时,可用选项如下之所以第三个参数有两种形态,是在旧版本中只存在一个布尔值,即属性但随着时间推移以及发展的需要,需要支持设置更多的特性设置,所以有了选项这个对象传参,又为了兼容以前的老程序,所以对两者进行了兼容。 起因 最近在看以前的代码时,发现年初在熟悉react hooks新特性时写下了这样一段代码: let i = 0; function Test(props) { c...

    jeyhan 评论0 收藏0
  • 由一篇ES6继承文章引发对于super关键字思考

    摘要:举个栗子中一段简单的继承代码实现使用了,不会报错这段代码非常简单,在子类中使用了关键字,编译时不会报错,也可以正常执行。参考资料从中的讲原型链与继承的静态属性和实例属性 问题引入 最近一直在看原型继承相关的东西,翻到这么一篇文章: 从ES6中的extends讲js原型链与继承 文中有一个点让我很感兴趣,箭头函数在继承过程中无法通过super关键字获取,这是为什么呢? 前置知识 MDN上...

    mudiyouyou 评论0 收藏0
  • 一个关于对象引用bug引发对于引用类型及数组简单思考

    摘要:图示如下而对于引用类型的复制可不是这样这个复制只是将的引用赋值给,二者是属于同一个引用,访问的都是堆内存中的同一个对象,任何一个该引用的变量发生变化,会对其余使用该引用的变量也发生变化。 这两天自己在写代码的时候,出现一个BUG,代码如下: class Car { constructor(carId) { this.position =...

    lijinke666 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<