JavaScript中prototype 为何是不能被打印显示的呢? 那么它的意义是什么?

prototype 为何是不能被打印显示的呢?
那么它的意义是什么?

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

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}

let person1 = new Person('John', 30);
person1.sayHello();   // 可调用
console.log(person1);  // 没有原型上被定义的数据
console.log(person1.prototype);  // undefined
阅读 1k
avatarAI BotBETA

在JavaScript中,prototype 不是一个实例对象可以直接访问的属性,这就是为什么你在尝试打印 person1.prototype 时会得到 undefined。实际上,每个函数对象都有一个 prototype 属性,该属性是一个指向原型对象的指针,而这个原型对象用于实现基于原型的继承与属性共享。

prototype 为何是不能被实例直接访问的?

  • 当你创建一个实例(如 person1)时,它内部有一个指向其构造函数(这里是 Person)的 prototype 对象的链接(通常被称为 __proto__,尽管这不是ECMAScript标准的一部分,而是某些JavaScript引擎实现的一个属性,用于访问内部 [[Prototype]] 链接)。这个链接是自动创建的,但你不能直接通过实例来访问或修改 prototype 属性,因为该属性是定义在函数对象(构造函数)上的。

prototype 的意义是什么?

  • 属性共享prototype 允许你在所有实例之间共享方法和属性。这意味着,一旦你在原型上定义了一个方法或属性,所有的实例都可以访问它,而不需要在每个实例上单独定义。这大大节省了内存。
  • 继承:基于原型的继承是JavaScript的核心特性之一。通过原型链,你可以实现复杂的继承关系,允许一个对象继承另一个对象的属性和方法。
  • 灵活性:虽然JavaScript的原型继承系统可能初看起来有些混乱,但它提供了极高的灵活性。你可以动态地修改原型,进而影响到所有基于该原型的实例。

示例说明

在你的例子中,Person.prototype.sayHello 是在 Person 构造函数的原型上定义的一个方法。所有通过 new Person(...) 创建的实例都会继承这个方法,但它们并不直接拥有 prototype 属性。相反,它们通过内部的 [[Prototype]] 链接(在大多数环境中通过 __proto__ 访问)来访问原型链上的方法和属性。

如何查看原型链

如果你想要查看实例的原型链,可以使用 Object.getPrototypeOf() 方法或 __proto__(尽管不推荐使用后者,因为它不是标准属性):

console.log(Object.getPrototypeOf(person1) === Person.prototype);  // true
console.log(person1.__proto__ === Person.prototype);  // 大多数环境中也是 true,但不推荐

这样,你就可以看到 person1 的原型确实是 Person.prototype,从而验证了原型链的存在和它的工作方式。

2 个回答

需要用 Object.getPrototypeOf(person1)

另外 console.log(person1) 里也是可以找到它的 prototype 上的属性的,只是不会直接显示子在 person1 下,而是在他的 <prototype> 下面(firefox,不同的浏览器/IDE 这个显示的“属性”名会有不同,因为这实际上不是一个“属性”,不是可以直接看到的)

新手上路,请多包涵
  1. "类"函数在执行new操作的时候会创建一个对象, 在这个例子把这个对象赋值给了person1
  2. 这个对象(person1)的内部链接[[Prototype]]会关联Person.prototype对象
console.log(Object.getPrototypeOf(person1) === Person.prototype); // true
  1. person1.sayHello()执行过程是:

    • person1对象上直接获取=>没有
    • person1的[[Prototype]]链上查找, 根据上面的第2条, [[Prototype]]会关联Person.prototype对象, 所以实际调用的是Person.prototype.sayHello
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏