zoukankan      html  css  js  c++  java
  • 知乎一道前端面试题详解,关于this的使用

    请说明要输出正确的myName的值要如何修改程序?并解释原因
    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
        alert(this.myName);
    }
    foo.prototype.bar = function(){
        setTimeout(this.sayHello, 1000);
    }
    var f = new foo;
    f.bar();

    先跟踪一下函数的执行。

    全局环境下,声明一个变量,实例化foo赋值给f,函数未执行。打印f,结果是:

    很显然,f就是一个foo的副本,它是一个对象,副本内部的函数就是该对象的方法,可以点式调用。foo是函数不可以直接作为对象调用内部方法。

    console.log(typeof f); //object
    console.log(typeof foo);  //function

    tips:函数foo内部声明的属性或方法前加this目的在于保护变量同时可以被实例化的对象访问,如果直接声明私有变量,无法实例化后使用,而若成为全局变量又可能造成污染。比如去掉setTimeout前的this,那么sayHello变成了全局变量,而若全局中未声明这个函数,就会造成错误。

    console.log(f.name);//Foo function

    对象f调用bar之后,被赋值的函数执行,this指向这个对象,然后setTimeout开始执行,指向window,f的方法sayHello在5s后被调起,此时它处在windows环境中,因此alert(this.myName)会尝试去window环境获取这个值。如下:

    var myName = "江太公";
    //or this.myName = "江太公";
    function sayHello(){alert("江太公");}
    foo = function(){
    this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
    alert(this.myName);
    }
    foo.prototype.bar = function(){
    setTimeout(this.sayHello, 5000);
    }
    var f = new foo;
    console.log(f);
    f.bar();
    console.log(f.bar);
    console.log(foo.bar);
    console.log(typeof f);
    console.log(typeof foo);
    // console.log(f.myName);

    结果弹出:江太公。证实我的想法。

    ok,整个执行流程很简单,但中间的this转换可能让人困惑。下面给出这道题的4种解决方案。

    方案一:用bind对this进行转向。

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
        alert(this.myName);
    }
    foo.prototype.bar = function(){
        setTimeout(this.sayHello.bind(this), 5000);
    }
    var f = new foo;
    f.bar();

    方案二:用call/apply进行转向。

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
        alert(this.myName);
    }
    foo.prototype.bar = function(){
        setTimeout(this.sayHello.apply(this), 5000);
    }
    var f = new foo;
    f.bar();

    方案三:用that进行hack。

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(that){
        alert(that.myName);
    }
    foo.prototype.bar = function(){
        var that = this;
        setTimeout(function(){that.sayHello(that);}, 5000);
    }
    var f = new foo;
    f.bar();

    方案四:使用箭头函数。

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
        alert(this.myName);
    }
    foo.prototype.bar = function(){
        setTimeout(()=>{this.sayHello()}, 5000);
    }
    var f = new foo;
    f.bar();

     或者:

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = ()=>{alert(this.myName)};
    foo.prototype.bar = function(){
        setTimeout(this.sayHello, 1000);
    }
    var f = new foo;
    f.bar()

    方法五:还有一种特特简单的办法,将构造函数的this也转向到全局。

    foo = function(){
        this.myName = "Foo function.";
    }
    foo.prototype.sayHello = function(){
        alert(this.myName);
    }
    foo.prototype.bar = function(){
        setTimeout(this.sayHello, 1000);
    }
    var f = new foo;
    foo();
    f.bar()

    发现其他途径烦请告我一声,谢谢。

  • 相关阅读:
    2020软件工程作业01
    问题清单
    2020软件工程个人作业06——软件工程实践总结作业
    感谢随笔
    2020软件工程作业05
    2020软件工程作业04
    2020软件工程作业03
    2020软件工程作业02
    2020软件工程作业01
    2020软件工程个人作业06——软件工程实践总结作业
  • 原文地址:https://www.cnblogs.com/jiangtian/p/6230501.html
Copyright © 2011-2022 走看看