Nodejs中JavaScript對象與原型

Nodejs中JavaScript對象與原型

JavaScript中有兩個特殊的對象:Object與Function。Object.prototype是所有對象的原型,處於原型鏈的最底層。Function.prototype是所有函數對象的原型,包括構造函數。我把JavaScript中的對象分爲三類,一類是用戶創建的對象,一類是構造函數對象,一類是原型對象。這三類對象中每一類都有__proto__屬性,通過它可以遍歷原型鏈,追溯到原型鏈的最底層。構造函數對象還有prototype屬性,指向一個原型對象,通過該構造函數創建對象時,被創建的對象的__proto__屬性將會指向構造函數的prototype屬性。原型對象有constructor屬性,指向它對應的構造函數。

例如下面的代碼:

function Foo(){
}
var foo = new Foo();
var obj = new Object();

爲了說明這之間複雜的關係,我畫了一個圖:

JavaScript prototype

JavaScript中通過原型實現繼承的本質就是一個對象可以訪問到它的原型鏈上任何一個原型對象的屬性,例如上圖foo對象,它擁有foo._proto__以及foo._proto._proto__所有屬性的淺拷貝(只拷貝基本數據類型,不拷貝對象)。所以可以直接訪問foo.constructor(來自foo._proto,即Foo.prototype),foo.toString(來自foo._proto_._proto_,即Object.prototype)。

http://www.byvoid.com/blog/javascript-object-prototype/


5 回复

Node.js 中 JavaScript 對象與原型

JavaScript 是一種基於原型的語言,其中對象和原型之間的關係是其核心特性之一。理解這些概念對於掌握 Node.js 的開發非常關鍵。

JavaScript 中的特殊對象

在 JavaScript 中,ObjectFunction 是兩個特殊的對象:

  • Object.prototype 是所有對象的原型,處於原型鏈的最底層。
  • Function.prototype 是所有函數對象的原型,包括構造函數。

對象的分類

根據用途,可以將 JavaScript 中的對象大致分為三類:

  1. 用戶創建的對象:例如,通過 {}new Object() 創建的對象。
  2. 構造函數對象:例如,通過 function Foo() {} 定義的函數。
  3. 原型對象:例如,Object.prototypeFunction.prototype

特殊屬性

這三類對象中每一類都有 __proto__ 屬性,通過它可以遍歷原型鏈,追溯到原型鏈的最底層。構造函數對象還有一個 prototype 屬性,指向一個原型對象。通過該構造函數創建的對象的 __proto__ 屬性將會指向構造函數的 prototype 屬性。原型對象有 constructor 屬性,指向它對應的構造函數。

示例代碼

function Foo() {
}

// 創建 Foo 的實例
var foo = new Foo();

// 創建一個普通的 Object 實例
var obj = new Object();

原型鏈的關係

為了更好地理解這些對象之間的關係,我們可以畫出以下圖表:

foo -> foo.__proto__ -> foo.__proto__.__proto__
     |                    |
     |                    +-> Object.prototype
     |
     +-> Foo.prototype
obj -> obj.__proto__ -> obj.__proto__.__proto__
     |                    |
     |                    +-> Object.prototype
     |
     +-> Function.prototype (如果 obj.__proto__ 是函數)

繼承機制

JavaScript 中通過原型實現繼承的本質就是一個對象可以訪問到它的原型鏈上任何一個原型對象的屬性。例如,foo 對象擁有 foo.__proto__ 以及 foo.__proto__.__proto__ 所有屬性的淺拷貝(只拷貝基本數據類型,不拷貝對象)。因此,可以直接訪問 foo.constructor(來自 foo.__proto__,即 Foo.prototype),也可以訪問 foo.toString(來自 foo.__proto__.__proto__,即 Object.prototype)。

希望以上內容能幫助你更好地理解 Node.js 中 JavaScript 對象與原型的關係。


foo._proto._proto所有屬性的淺拷貝(只拷貝基本數據類型,不拷貝對象)

对这句有疑问,应该是都做任何拷贝吧?而是需要的时候去沿着链"查找"

现在看感觉清晰多了. 好帖!

问一个问题: 我直接在交互模式下定义function,然后创建对象,发现交互模式直接可以显示对象的原型方法. 不过将同样的代码写成js文件,通过node debug模式,用repl跟踪时,发现对象的原型方法不是直接显示的(当然通过__proto__可以看到). 有谁清楚这个吗?

在Node.js中,JavaScript对象与原型是理解面向对象编程的关键概念。原型链使得对象可以继承属性和方法,并且允许动态地向对象添加新的属性和方法。下面是关于这一主题的一些核心要点,包含了一些示例代码。

1. __proto__ 属性

__proto__ 属性指向当前对象的原型对象。所有对象都继承自一个原型对象,可以通过这个属性访问。

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function() {
    console.log(`Hello, I'm ${this.name}`);
};

const person1 = new Person('Alice');
console.log(person1.__proto__ === Person.prototype); // true
person1.greet(); // Hello, I'm Alice

2. 构造函数与原型对象

构造函数的prototype属性指向一个对象,该对象的属性会被所有通过构造函数创建的对象共享。

function Animal(type) {
    this.type = type;
}

Animal.prototype.move = function() {
    console.log(`${this.type} is moving`);
};

const dog = new Animal('Dog');
dog.move(); // Dog is moving

3. 原型链的继承

当查找一个对象的属性时,如果当前对象没有找到,则会沿着原型链继续向上查找。

function Vehicle() {}
Vehicle.prototype.start = function() {
    console.log('Engine started');
};

function Car() {}
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.drive = function() {
    console.log('Driving...');
};

const myCar = new Car();
myCar.start(); // Engine started
myCar.drive(); // Driving...

4. 原型对象的constructor属性

每个原型对象都有一个constructor属性,指向其对应的构造函数。

console.log(Car.prototype.constructor === Car); // true

以上代码展示了如何使用原型和原型链来实现继承,以及如何利用这些机制来创建和管理对象。希望这能帮助你更好地理解Node.js中JavaScript的原型机制。

回到顶部