【问题标题】:Understanding JavaScript in detail: is it a class, a function, or just a variable?详细了解 JavaScript:它是一个类、一个函数还是一个变量?
【发布时间】:2016-04-05 23:21:23
【问题描述】:

我是 JavaScript 的初学者,我发现一个概念非常混乱。考虑下面的代码:

var person = {
     firstName   :"Penelope",
     lastName    :"Barrymore",
     // Since the "this" keyword is used inside the showFullName method below, and the showFullName method is defined on the person object,​
     // "this" will have the value of the person object because the person object will invoke showFullName ()​
     showFullName:function () {
         console.log (this.firstName + " " + this.lastName);
     }
​
 }
​
 person.showFullName (); // Penelope Barrymore

人是一个类或函数还是只是一个变量?

如果假设那个人是一个类,那么代码person.showFullName (); 是不是调用它的正确方式,因为在 C# 或我们编写的任何其他语言中

person perObj = new person();
perObj.showFullName();

?

【问题讨论】:

  • 我也一直觉得这很令人困惑。而且不可靠。我很想看到详细的答案,但我的解决方案总是:不要使用它,它不会咬你。我会创建一个function Person,然后是一个person = new Person。有时全静态就足够了,然后我会在任何地方使用person.firstName 等,所以没有this。当然只是一个意见。
  • 您觉得哪些方面令人困惑或不可靠?对象可以有方法的事实?
  • 在 JavaScript 中你确实没有有类(虽然它们可以被模拟)。在这里,对象直接继承自其他对象。你应该阅读 JS 原型。
  • 忘记任何其他语言的课程。
  • var person ... 提示:var 表示“变量”,那么人可能是什么?

标签: javascript javascript-objects


【解决方案1】:

您的代码中的personobject。也就是说personObject的一个实例,person原型与其他对象中的原型相同,由{}初始化器创建:

// Object initialiser or literal
person = {
  some methods and properties
}

// Called as a constructor
person = new Object({some methods and properties})

也就是说你的person对象从prototype继承了Objects特定的方法,比如hasOwnProperty()toString()valueOf()等。

上次写的Object constructor 不仅可以创建“类似哈希”的对象,还可以创建任何其他类型的对象(数组、字符串等)。 javascript 中的所有内容都是对象,甚至是基元(它们有包装对象,并且有自己的构造函数)。

示例:

persons     = new Object([person_1, person_2, person_3])    
person_age  = new Object(18)
person_name = new Object('John')

我们可以用其他语法编写以上所有表达式:

persons     = new Array(person_1, person_2, person_3) //or      
persons     = [person_1, person_2, person_3]

person_age  = new Number(18) //or    
person_age  = 18

person_name = new String('John') //or    
person_name = 'John'

可以使用适当的全局对象创建字符串和数字,而无需 new

Page on MDN

新对象类型

如果需要创建新类型的对象,必须定义新的构造函数并定义原型(ECMAScript 5.1)

NewObjectType = function(arg1, arg2){
   this.arg1 = arg1 //define object's property arg1
   this.arg2 = arg2 //define object's property arg2

   private_function = function(){}
   this.public_function = function(){} //this function can't be inherited, because not in prototype
}

NewObjectType.prototype = {
   constructor : NewObjectType,
   public_inheritable_function_1 : function(){},
   public_inheritable_function_2 : function(){}
}

//creating new instance of NewObjectType:

my_new_object = new NewObjectType(arg1, arg2)

my_new_object instanceof NewObjectType //true
my_new_object instanceof Object        //true, because prototype was created with {} literal, and Object's prototype built into the prototype chain

说明:

new NewObjectType 被调用时,NewObjectType 的新实例将被创建。 NewObjectType 构造函数的Prototype 属性将与新实例的隐藏__proto__ 属性链接。

没有原型的对象

如果需要创建没有Object的方法的清晰对象,则必须使用create方法创建没有原型:

person = Object.create(null)

它可能作为简单的键值存储有用

类型,不是从 Object 继承的

如果需要在原型链中创建没有对象原型的新类型对象,可以使用以下语法:

NewObjectType = function(arg1, arg2){}
NewObjectType.prototype = Object.create(null)
NewObjectType.prototype.constructor = NewObjectType 
NewObjectType.prototype.public_inheritable_function = function(){}

my_new_object = new NewObjectType(arg1, arg2)

my_new_object instanceof NewObjectType //true
my_new_object instanceof Object        //false

【讨论】:

    【解决方案2】:

    人是一个类或函数还是只是一个变量?

    JavaScript 没有类。变量 person 是一个变量,指向一个存放对象的内存位置。

    对象本身有几个方面。附加了一组属性,这些属性都附加到 person 对象。这些属性之一包含一个作为函数对象的值。该函数对象包含一个执行上下文。

    Execution ContextECMA 有一个本地环境、一个词法环境和一个 this 绑定。 this 绑定指向 person 对象。函数的本地环境限定为函数内部的声明,函数的词法环境限定为 Person 对象可用的声明。

    【讨论】:

      【解决方案3】:

      person 实际上是 JavaScript 中的对象字面量。对象字面量是那些被定义为

      var obj = {
          // Properties and methods
      };
      

      它们的类型是对象。在 JavaScript 中,我们没有任何称为 class 的东西。

      • 一切都是一个对象。 (偶函数)

      对象字面量是用大括号括起来的名称-值对的逗号分隔列表。对象字面量封装数据,将其封装在一个整洁的包中。

      http://www.dyn-web.com/tutorials/object-literal/


      虽然我们在 ECMAScript 6 中确实有类,但它们不像其他语言那样是真正的类。

      MDN 说:

      JavaScript 类是在 ECMAScript 6 中引入的,并且是语法 sugar 优于 JavaScript 现有的基于原型的继承。这 类语法引入了新的面向对象继承 模型转换为 JavaScript。 JavaScript 类提供了一个更简单和 更清晰的语法来创建对象和处理继承。

      【讨论】:

      • JS 没有真正的类,但有一个 class 语法,所以从技术上讲,我们确实有 something 称为类。
      • @StefanBaiu 是的,我们有一个名为class 的关键字,但它不像其他编程语言那样用作常规类。在 JavaScript 中,我们只能通过new 运算符和构造函数(仍然是对象类型)来模拟类的角色。
      • @StefanBaiu 所以 everything 是除了原始类型之外的对象。
      • 定义“真正的类”。 javascript 类在什么意义上是不真实的?
      • @Bergi 是的,我知道。对象字面量是我们可以用来定义对象的语法。那些不是类型。我的句子可能有些误导。我将编辑我的答案。
      【解决方案4】:

      它是一个对象,而不是一个类。

      这样考虑:

      在其他经典的 OO 语言中,当您实例化一个时, 你得到一个实例;这个实例相当于一个 JavaScript object -

      JavaScript 对象是属性的动态“包”。它是一组名称-值对,这些值可以是任何类型 - 函数或对象本身。

      在您的情况下,firstName, lastName, and showFullName 是人​​员对象的属性。

      您可以使用点 (.) 表示法访问对象的属性, 例如:person.firstName, person.showFullName()

      【讨论】:

        【解决方案5】:

        只是添加到 Barmar,您也可以这样做(以防您发现它更类似于 C#):

        var person = function() {
             this.firstName = "";
             this.lastName = "";
        } 
        
        person.prototype.showFullName = function () { 
             console.log (this.firstName + " " + this.lastName); 
        } 
        
        var perObj = new person();
        perObj.firstName = "Penelope";
        perObj.lastName = "Barrymore";
        perObj.showFullName();
        

        【讨论】:

          【解决方案6】:

          person 是一个对象。它有 3 个属性,分别命名为 firstNamelastNameshowFullName。前两个属性包含字符串。最后一个属性包含一个函数。

          当您使用语法<expression>.<function>(<arguments>) 调用函数时,其中<expression> 计算为一个对象,<function> 是其属性之一的名称,然后在函数运行时设置特殊变量this到对象。这就是this.firstNamethis.lastName 能够访问对象的这些属性的方式。

          当只有一个对象时,这个功能不是很有用,因为它可以很容易地只使用person 变量。但是你可以对多个对象使用相同的函数。

          function showFull() {
              console.log(this.firstName + " " + this.lastName);
          }
          var person1 = {
              firstName: "Penelope",
              lastName: "Barrymore",
              showFullName: showFull
          };
          var person2 = {
              firstName: "John",
              lastName: "Smith",
              showFullName: showFull
          }
          person1.showFullName(); // Penelope Barrymore
          person2.showFullName(); // John Smith
          

          【讨论】:

          • @user5283721:当 Barmar 说“person 是一个对象”时。他正在简化一点,以避免一次向你扔太多东西。现在您已经阅读了他的答案,我们可以说person 是一个引用对象的变量。
          【解决方案7】:

          JavaScript 没有类或者不是基于类的语言。相反,我们说它是一种基于原型的语言。

          【讨论】:

          • 那么 ECMA6 确实有类:P 所以你的答案现在可能无效。
          • @Nirus:ES2015 (ES6) 有class 语法。它仍然是原型继承,它只是表达原型继承的另一种语法,如果你想使用构造函数,它会降低正确设置它的复杂性。
          • @T.J 我同意你的看法。但这必须详细说明,因为 OP 是该语言的新手。
          • @Nirus:我认为 JS 没有类的概念是每个语言新手都应该理解的第一件事。
          • @Bergi:我知道,你也知道。或者更确切地说,JavaScript 是否有类是一个观点问题。我的观点是它以任何真正重要的方式发挥作用,因为这种语言是那个灵活的。关键是无论哪种方式,它都是原型继承,而新语法只是简化了设置。不是 ES2015 增加了类,只是增加了class 语法。
          猜你喜欢
          • 1970-01-01
          • 2011-08-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-20
          • 2021-05-31
          • 1970-01-01
          • 2021-06-29
          相关资源
          最近更新 更多