【问题标题】:Why is 'this' keyword required inside constructor function in JavaScript? [duplicate]为什么 JavaScript 的构造函数中需要“this”关键字? [复制]
【发布时间】:2019-09-05 05:34:37
【问题描述】:

我正在尝试使用 JavaScript 中的 new 关键字来实例化构造函数。但是,它没有按预期工作 -

var a = function () {
            abc = function () {
                      return  "abc";
                  }
        }

var obj = new a();

如果我这样做-

obj.a(); 。它说-

Uncaught TypeError: obj.abc is not a function

但如果我只是在没有对象 obj 的情况下访问它,它就可以工作

abc();

但是如果我使用this 作为内部函数,整个问题就解决了-

var a = function () {
            this.abc = function () {
                           return  "abc";
                       }
        }

所以我的问题是,如果我声明 abc() 没有 'this' 关键字,它的作用域不是在 a 函数内。为什么当它在函数 a 中声明时被视为全局函数?

【问题讨论】:

  • 当您执行 obj.a() 时,它会显示 obj.abc 不是函数”?!请在此处仔细检查您的姓名。
  • 已编辑。这是错字

标签: javascript function object scope this


【解决方案1】:

如果我在没有 this 关键字的情况下声明 abc(),它的作用域不是在 a() 函数内。为什么在函数 a 中声明它时被视为全局函数?

它没有在任何地方声明a 中的代码分配给一个未声明的变量,这会创建一个隐式全局(在松散模式下,默认设置)。

这是使用严格模式的众多充分理由之一(脚本顶部的"use strict";)。在严格模式下,分配给未声明的变量是错误的(就像从未声明的变量中读取一样)。更多内容见我的博文The Horror of Implicit Globals


是的,正如您所发现的,this. 在 JavaScript 中绝不是可选的,就像在 Java 或 C# 中一样。要在执行new a() 时引用在a 中创建的实例,必须使用this

旁注:JavaScript 中压倒性的约定是构造函数(通过new 调用的函数)以大写字母开头。所以A而不是a,或者Example

var Example = function () {
    this.abc = function(){
        return "abc";
    };
};

var obj = new Example();
console.log(obj.abc());

您可以考虑将abc 放在原型上,而不是在每次调用a 时重新创建它:

var Example = function () {
};
Example.prototype.abc = function(){
    return "abc";
};

var obj = new Example();
console.log(obj.abc());

或者使用 ES2015+ class 语法:

class Example {
    abc(){
        return "abc";
    }
}

var obj = new Example();
console.log(obj.abc());

【讨论】:

    【解决方案2】:

    那是因为您没有将 abc 声明为新构造对象的属性 - 您通过省略 var 关键字使其成为全局可用的函数。如果您想在不使用 this 的情况下使其可访问,请尝试以下操作:

    var a = function() {
      var abc = function() {
        return "abc";
      }
      return { abc };
    }
    
    var obj = new a();
    console.log(obj.abc());

    【讨论】:

    • a已经被new调用时,为什么要从a创建并返回一个新对象(它没有a.prototype作为它的原型),所以一个新对象(使用正确的原型)已经创建了吗? eOP 需要做的就是他们在问题中显示的内容:this.abc = function() { /*...*/ };
    • "那是因为你没有将 abc 声明为一个属性……",你的意思是作为一个变量,属性被创建了。 ;-)
    • (天哪,我上面评论中的错别字数量。叹息
    【解决方案3】:

    声明一个没有任何键的变量/函数将使其成为全局变量/函数:

    abc();
    
    abc = function() {
      console.log('global abc');
    };
    
    // same as:
    //window.abc = function() {...};
    window.abc();

    使用let,您的函数将被限定范围:

    {
      let abc = function() {
        console.log('let abc');
      }
    }
    
    abc(); // ReferenceError: abc is not defined

    如果你用var声明一个函数,你将能够在闭包结束后执行它,但不能在之前执行,如果没有在函数内声明:

    //abc(); // TypeError: abc is not a function
    
    {
      var abc = function() {
        console.log('var abc');
      }
    }
    
    abc(); // will work
    
    let a = function() {
      var cde = function() {
        console.log('var cde');
      }
      
      cde(); // will work
    }
    
    cde(); // ReferenceError: cde is not defined

    最后,this 将创建一个对象属性:

    let a = function() {
        this.abc = function() {
          console.log('this.abc');
        };
    }
    
    let obj = new a();
    obj.abc();
    
    a.abc(); // TypeError: abc is not a function

    【讨论】:

    • 你好,我想知道为什么在构造函数中需要这个?如果我不使用它,则内部函数将被分配给全局范围。为什么?
    • T.J. Crowder 's answer。解释得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    相关资源
    最近更新 更多