一周一章前端书·第6周:《你不知道的JavaScript(上)》

作者: 梁同学de自言自语 | 来源:发表于2017-11-04 15:18 被阅读8次

    第二部分 - 第1章:关于this

    1.1 为什么要用this

    • this是一个很特别的关键字,同时也是JavaScript中很复杂的机制,本章讲解this
    • 我们先看看,不用this的代码是怎么样的:
    var Me = {
        name : 'William'
    }
    
    var You = {
        name : 'Yoki'
    }
    
    //公共方法:返回指定对象的大写name
    function identify(context){
        return context.name.toUpperCase(); 
    }
    
    //公共方法:用指定对象大写的name,输出hello字符串
    function speak(context){
        var greeting = "Hello,I'm " + identify(context);
        console.log(greeting);
    }
    
    console.log(identify(You));
    console.log(identify(Me));
    speak(Me);
    speak(You);
                
    
    • speak()identify()方法不使用this,则需要显式的传入context对象,而随着代码越来越复杂,显式传递对象的方式会使得代码愈加混乱。
    • 接着我们改写这两个方法,会发现,其实this提供了一种更优雅的方式隐式传递对象的引用,这样API也可以设计得更加简洁且复用。
    function identify(){
        return this.name.toUpperCase(); 
    }
    
    function speak(){
        var greeting = "Hello,I'm " + identify.call(this);
        console.log(greeting);
    }
    
    console.log(identify.call(You));
    console.log(identify.call(Me));
    speak(Me);
    speak(You);
    

    1.2 this的误解

    • 人们很容易把this理解成指向函数自身,这从英语的语法上理解是没毛病的,但事实并不是这样的。
    function foo(num){
       console.log("foo:" + num);
       this.count++;
    }
    
    foo.count = 0;
    
    for(var i=0;i<10;i++){
        if(i > 5){
            foo(i);
        }
    }
    
    console.log(foo.count);
    console.log(count);
    

    控制台输出的是:

    foo:6
    foo:7
    foo:8
    foo:9
    0
    NaN
    
    • 从上述打印情况来看,console.log()语句确实产生了4条输出,证明foo()方法被调用了4次,但this.count的指向并不是foo.count,反而在window下多出了一个count,值为NaN
    • 为了修复上述的结果,当然可以将foo方法中的this.count++改成foo.count++,但忽略了真正的问题——this究竟指向谁?
    • 下面我们来真正修复这个问题,其实只需要修改foo()方法调用的方式即可:
    for(var i=0;i<10;i++){
        if(i > 5){
            //call()方法就是指明哪个对象来调用方法
            //之前没使用call()方法时,默认是以window来调用方法,以致于window下会多个count=NaN的变量
            foo.call(foo,i);
        }
    }
    
    console.log(foo.count);
    
    • 这下输出就正常了,由此可以看出其实this真正的含义是:谁调用我,我指向谁
    • 另外需要注意的是,不能通过this进行作用域穿越。
    function foo(){
        var a = 2;
        bar();
    }
    
    function bar(){
        console.log('a:' + this.a);
    }
    
    foo();
    
    • 代码试图通过this关联foo()bar()作用域,从而让bar()能访问foo()作用域中的变量,这是不可能实现的。

    1.3 this到底是什么

    • this在运行时绑定,而不是编写时,它的指向取决于函数的调用方式。
    • JavaScript当函数被调用时,会创建一个context(上下文/环境)记录,这个记录的内容包含函数在哪里被调用、函数的调用方式、 传入的参数等信息,而this就是函数context记录的其中一个属性。

    相关文章

      网友评论

        本文标题:一周一章前端书·第6周:《你不知道的JavaScript(上)》

        本文链接:https://www.haomeiwen.com/subject/phnfmxtx.html