详细了解 JavaScript:它是一个 class、一个函数,还是只是一个变量?

Understanding JavaScript in detail: is it a class, a function, or just a variable?

我是 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

人是 class 还是函数还是只是一个变量?

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

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

?

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

JavaScript 没有 类 或者不是 class-based 语言。相反,我们说它是一种 prototype-based 语言。

补充一下 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();

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

这样想:

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

JavaScript 对象是动态的 "bags" 属性。它是一组 name-value 对,这些值可以是任何类型 - 函数或对象本身。

在你的例子中,firstName, lastName, and showFullName 是 person 对象的属性。

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

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

var obj = {
    // Properties and methods
};

并且它们的类型是对象。在 JavaScript 中我们没有任何叫做 class 的东西。

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

An object literal is a comma-separated list of name-value pairs wrapped in curly braces. Object literals encapsulate data, enclosing it in a tidy package.

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


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

MDN 说:

JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.

Is person a class or function or just a variable?

JavaScript 没有 类。变量 person 是指向保存对象的内存位置的变量。

对象本身有几个方面。有一组附加的属性都附加到 person 对象。其中一个属性包含一个值,它是函数对象。这个函数对象包含一个执行上下文。

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

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

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

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

这意味着你的person对象从原型继承对象特定的方法,例如hasOwnProperty()toString()valueOf()

最后写的 Object constructor 不仅可以创建 "Hash-like" 对象,还可以创建任何其他类型的对象(数组、字符串等)。 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__ 属性 链接。

没有原型的对象

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

person = Object.create(null)

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

类型,不是从对象继承的

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

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