【问题标题】:Confusing JavaScript statement: "var x = new this();"令人困惑的 JavaScript 语句:“var x = new this();”
【发布时间】:2011-03-29 06:22:02
【问题描述】:

我以为我理解了 JavaScript 原型对象的概念,以及 [[proto]],直到我看到一些关于类继承的帖子。

首先,http://amix.dk/blog/viewEntry/19038 上的“JavaScript OOP - 智能方式”

参见实施部分:

var parent = new this('no_init');

还有 John Resig 伟大博客上的“简单 JavaScript 继承”。

var prototype = new this();

new this(); 究竟是什么意思?

这句话对我来说毫无意义,因为我的理解是this 指向一个对象而不是构造函数。我还尝试在 Firebug 中测试语句来解决这个问题,但我收到的只是语法错误。

我的脑袋彻底晕了。

谁能详细解释一下?

【问题讨论】:

  • 请注意:不要将 JavaScript 对象引用与指针混淆。 this“指”一个对象,而不是“指向”。

标签: javascript class inheritance


【解决方案1】:

查看此链接http://www.quirksmode.org/js/this.html 它会告诉您有关 this 关键字的信息,但我不确定 this() 是什么,可能是它的某种用户定义函数……您不知道...

【讨论】:

  • new this() 就像var MyClass = this; new MyClass()new this() 中的 this() 没有什么特别之处。
【解决方案2】:

“this”表示当前运行的函数的上下文。

您发布的代码肯定出现在充当对象方法的函数中。 所以对象就是函数的上下文。

"new this()" 将在使用传递的参数运行其构造函数后返回当前对象的克隆。

【讨论】:

    【解决方案3】:

    this() 指的是代码所在的函数,但 this() 必须在该函数内。调用新的 this();在函数内会创建一个永无止境的循环。在函数之外调用它是多余的,因为没有设置为 this() 的函数/类。

    【讨论】:

    • 循环将完全依赖于上下文,this 并不必然引用当前函数,在这种情况下它确实引用了当前对象的定义,因为我们在对象的原型中,但在事件处理程序中说 this 根本不引用当前函数。
    • 是的; this 由调用绑定,而不是在创建函数时绑定。否则,通过原型的委托无法正常工作!
    【解决方案4】:

    AJS.Class 有效地* 翻译了这个:

    var Person = new AJS.Class({
        init: function(name) {
            this.name = name;
            Person.count++;
        },
        getName: function() {
            return this.name;
        }
    });
    Person.count = 0;
    

    进入这个:

    var Person = function (name) {
        this.name = name;
        Person.count++;
    };
    
    Person.prototype = {
        getName: function() {
            return this.name;
        }
    };
    
    Person.extend = AJS.Class.prototype.extend;
    Person.implement = AJS.Class.prototype.implement;
    
    Person.count = 0;
    

    因此,在这种情况下,AJS.Class.prototype.extend 中的this 指的是Person,因为:

    Person.extend(...);
    // is the same as
    Person.extend.call(Person, ...);
    // is the same as
    AJS.Class.prototype.extend.call(Person, ...);
    

    * 有很多案例我没有详述;这种重写是为了简单地理解问题。

    【讨论】:

    • 您对这个问题的帮助非常棒。非常感谢,我真的很感激:)。在我将此标记为答案之前-我希望您能确认我的理解。本质上,this 仍然“引用”extend() 中的 Function 对象(例如上面的函数 Person())。它不是一个非函数对象。
    • @user419125,嗯?我不太明白你在这里所说的话。 FunctionObject;它是Object 的一种特殊类型(如果你愿意的话,它是一个“子类”,具有一些其他特殊语义)。
    • 问对面的@AdamMikulasev,如果this 在执行new this() 时不是一个函数,它会抛出一个异常,所以它必须是一个函数。唯一的谜团是它是如何被初始化的。这是一个这样的示例function y(){};y.a=function(){return this instanceof Function;};y.a();,它说明了@strager 提出的观点,即函数(在本例中为y)只是另一个可以具有其值可以是函数(在本例中为a)的属性的对象,它可能被调用(在这种情况下,this 是一个作为函数的对象,因此new this() 将是有效的)。
    【解决方案5】:

    我认为,让您感到困惑的是“this”的真正来源。所以请多多包涵——这里有一个非常简短的解释,我希望能把它说得很清楚。

    在 JavaScript 中,函数中的“this”指的是什么,总是在函数被调用时确定。当你这样做时:

    jimmy.nap();

    nap 函数(方法)运行并接收 jimmy 作为“this”。

    哪些对象引用了 nap 是无关紧要的。例如:

    var jimmy = {}, billy = {};
    jimmy.nap = function(){ alert("zzz"); };
    var jimmy_nap = jimmy.nap;
    jimmy_nap(); // during this function's execution, this is *NOT* jimmy!
                 // it is the global object ("window" in browsers), which is given as the 
                 // context ("this") to all functions which are not given another context.
    billy.sleep = jimmy.nap;
    billy.sleep(); // during this function's excution, this is billy, *NOT* jimmy
    jimmy.nap(); //okay, this time,  this is jimmy!
    

    换句话说,只要你有:

    var some_func = function(arg1, arg2){ /*....*/ };
    // let's say obj and other_obj are some objects that came from somewhere or another
    obj.some_meth = some_func;
    other_obj.some_meth = some_func;
    obj.some_meth(2, 3);
    other_obj.some_meth(2, 3);
    

    它被“翻译”成的内容(不是字面意思——这是教学法,而不是关于 javascript 解释器的实际工作方式)是这样的:

    var some_func = function(this, arg1, arg2){ /* ...*/ };
    // let's say obj and other_obj are some objects that came from somewhere or another
    obj.some_meth = some_func;
    other_obj.some_meth = some_func;
    obj.some_meth(obj, 2, 3);
    other_obj.some_meth(other_obj, 2, 3);
    

    因此,请注意该页面上的示例中如何使用扩展:

    UniversityPerson = Person.extend({ /* ... */ });
    

    小测验:当extend 运行时,它认为“this”指的是什么? 答:没错。 “人”。

    所以上面令人费解的代码确实与(在那种特定情况下)相同:

    var prototype = new Person('no_init');
    

    不再那么神秘了,嗯?这是可能的,因为与某些语言不同, JavaScript 变量(包括“this”)可以保存任何值,包括 Person 等函数。

    (没有什么可以使 Person 成为一个构造函数。任何函数都可以用 new 关键字调用。如果我回想一下确切的语义,我认为当一个函数用 new 关键字调用时,它会自动给出一个空对象({})作为其上下文(“this”),当函数返回时,返回值是同一个对象,除非(也许?)函数返回其他东西)

    这是一个很酷的问题,因为它说明了 JavaScript 整洁或古怪的一个非常重要的部分(取决于你如何看待它)。

    这是否回答了您的问题?如有必要,我可以澄清。

    【讨论】:

    • 构造函数被赋予一个空对象,其中填充了prototype 成员(简而言之)。此外,虽然您的结论是正确的(即this 绑定到Person),但Person.extend 最终如何成为AJS.Class.prototype.extend 的值? (我知道答案;我只是说你没有在答案中提到它。)
    • 我认为这应该是选择的答案。很有道理。
    【解决方案6】:

    想象以下情况:

    var inner = function () {
        var obj = new this;
        console.log(obj.myProperty);
    };
    
    var f1 = function () {
        this.myProperty = "my Property"
    }
    
    f1.f2 = inner;
    f1.f2();
    

    这里调用对象本身就是一个函数,所以this会返回一个函数,我们可以instantiate it

    为了使用 this()(不是 this),外部函数(上下文)本身必须返回可以实例化的 smth(另一个函数):

    var inner = function () {
        var obj = new this();
        console.log(obj.myProperty);
    };
    
    var f1 = function () {
        var func = function () {};
        func.myProperty = 'my property';
        return func;
    };
    
    f1.f2 = inner;
    f1.f2();
    

    【讨论】:

      【解决方案7】:

      在 javascript static 函数中,您可以像这样调用 new this()

      var Class = function(){}; // constructor
      Class.foo = function(){return this;} // will return the Class function which is also an object
      

      因此,

      Class.foo = function(){ return new this();} // Will invoke the global Class func as a constructor
      

      这样你就得到了一个静态工厂方法。这个故事的寓意是,当你不调用它们时,不要忘记函数就像任何其他对象一样。

      【讨论】:

        【解决方案8】:

        更简单的代码解释:

        class User {
          constructor() {
            this.name = '';
            this.age = '';
          }
          static getInfo() {
            let user = new this();
            console.log(user);
          } 
        }
        
        User.getInfo()
        

        输出:

        Object {
          age: "",
          name: ""
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-17
          • 1970-01-01
          • 2016-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多