zoukankan      html  css  js  c++  java
  • JS 作用链,箭头函数 this 取值

      通俗地讲,当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链。

      1.当执行函数时,总是先从函数内部找寻局部变量。

      2.如果内部找不到(函数的局部作用域没有),则会向创建函数的作用域(声明函数的作用域)寻找,依次向上。

      比如在闭包中可以直接使用外部函数内定义的变量,这也是闭包的本质:闭包函数的定义基于外部函数的执行。

    function outer(){
        let outerSay= 'i am outer';
        function inner(){
            console.log(outerSay);
        }
        return inner;
    }
    
    outer()();

      运行结果:

      闭包函数访问到了外层函数定义的变量。也就是声明闭包函数时的外层作用域中的变量。

      以另一个例子作对比:

    var name = "windowName";
    
    function f1() {
        var name = "f1Name";
        console.log("f1 say : ",name);
        f0();
    }
    
    
    function f0() {
        console.log("f0 say :",name);
    }
    
    f1();

      运行结果:

      对于 f1 而言,在其内部声明了 name 变量,所以首先会找到函数内部定义的变量。而对 f0 而言,函数内部没有定义内部变量,需要从函数定义时的外层环境寻找,也就是全局变量 name 。而不是 f1 中定义的局部变量内部, f1 的环境是调用 f0 的外部环境,而不是声明 f0 的外部环境。

      相对于变量的取值取决于函数定义时的环境,this 的取值正相反,取决于函数运行时的上下文。this是使用call方法调用函数时传递的第一个参数,它可以在函数调用时修改,在函数没有调用的时候,this的值是无法确定。对于函数的调用:

    const obj = {
        name: 'Jerry',
        greet: function() {
            console.log(this.name)
        }
    }
    obj.greet()  //第一种调用方法
    obj.greet.call(obj) //第二种调用方法

      对于函数的调用,第一种方式只是第二种方式的语法糖。函数在调用时需要传入调用对象。当使用第一种方法调用普通函数时,有以下规则:

      1. 一般方法中,this代指全局对象 window

      2. 作为对象方法调用,this代指当前对象

      3. 作为构造函数调用,this 指代new 出的对象()

      4. 调用方法的apply和call方法,可以改变函数的调用对象/作用域

      而对于箭头函数来说,箭头函数本身是没有 this 的,call 传入的第一个参数会被忽略。在严格模式下,this 为 undfined,否则为 window。箭头函数的 this 取决于执行上下文中的 this 。当作为闭包函数时,执行上下文中有外层函数的 this ,在箭头函数中使用 this 会直接使用外层函数的 this。闭包函数的定义取决于外部函数的执行。

      其他情况下箭头函数的 this 均指向 undfined(严格模式)或 window。

      对于普通函数来说,做为闭包函数时,其 this 指向的是 window 对象。因为其并没有被作为对象的方法调用,call 方法传入的第一个方法为 window 。

      可以说闭包函数的 this 是一个特例,其忽略了 call 中传入的第一个参数,不可人为指定 this,this 只会从执行上下文中去寻找。

      举个例子:

    var name = 'windowName';
    var obj = {
        name: 'outerName',
        inner0: function() { console.log('inner0 say : ', this.name); },
        inner1: () => { console.log('inner1 say : ', this.name) }
    }
    obj.inner0();
    obj.inner1();

    var name = 'windowName';
    var obj = {
        name: 'outerName',
        inner0: function() {
            setTimeout(function() {
                console.log('inner0 say : ', this.name);
            }, 10)
    
        },
        inner1: function() {
            setTimeout(() => {
                console.log('inner1 say : ', this.name);
            }, 10)
        }
    }
    obj.inner0();
    obj.inner1();

      

      

     

  • 相关阅读:
    一个小判卷系统
    关于int main(int argc,char* argv[])详解
    2014微软编程之美复赛的解题报告
    解题报告CF266B 384A 339A
    由于第一天在博客园开博客,我随便写个解题报告吧,以前很少写
    阿里巴巴大数据竞赛
    新注册的博客,欢迎大家多多指教
    vue中forceupdate的使用
    钉钉小程序之参数有中文。encodeUri以及encodeURIComponent详解
    关于offsetX、offsetY、clientX、clientY、pageX、pageY、screenX、screenY的区别
  • 原文地址:https://www.cnblogs.com/niuyourou/p/14198167.html
Copyright © 2011-2022 走看看