本文详细解析JavaScript基于原型对象的继承模型,阐述prototype与__proto__的关系,并通过代码示例说明new关键字在创建实例、设置原型及初始化对象时的具体行为,帮助读者理清原型链的形成过程与核心机制。
原型基础概念
原型
众所周知,JavaScript 摒弃了传统的类继承模型,转而采用基于 原型的设计模式。其核心代码实现大致如下所示。
function Student(name){
this.name = name;
}
var Kimy = new Student("Kimy");
Student.prototype.say = function(){
console.log(this.name + "say");
}
Kimy.say();
//Kimysay
以对象 Kimy 为例,它自身并未定义 say 方法。当在实例中无法找到该方法时,引擎会沿着原型链向上查找,即在 Student.prototype 对象中寻找。这一过程依赖于构造函数 Student 的定义。
构造函数与原型链关系
构造函数、__proto__ 以及原型链
除 IE 浏览器外,主流浏览器均在 Object 对象的实例上部署了非标准的 属性(前后各两个下划线),该属性指向对象的原型对象,即对应构造函数的 属性。
此处引用一段代码及示意图进行说明。
// 构造方法
function Foo(y) {
this.y = y;
}
Foo.prototype.x = 10;
// 继承方法"calculate"
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
};
// 使用foo模式创建 "b" and "c"
var b = new Foo(20);
var c = new Foo(30);
// 调用继承的方法
b.calculate(30); // 60
c.calculate(40); // 80
console.log(
b.__proto__ === Foo.prototype, // true
c.__proto__ === Foo.prototype, // true
b.constructor === Foo, // true
c.constructor === Foo, // true
Foo.prototype.constructor === Foo // true
b.calculate === b.__proto__.calculate, // true
b.__proto__.calculate === Foo.prototype.calculate // true
);

观察可知,每个对象均包含一个 属性。例如,对象 b 的 指向创建它的构造函数 Foo 的 属性;而 Foo.prototype 本身也是一个对象,其 指向构造它的构造函数 Object 的 。由于 Object.prototype 的 指向 null,从而构成了完整原型链。
理解以下代码片段同样关键。
Object instanceof Function
//true
Function instanceof Object
//true
new 关键字的执行机制
new 做了什么
此外需注意,JavaScript 中普通函数与构造函数在语法形式上差异不大(首字母大写并非强制要求,但通常约定构造函数首字母大写)。那么,new 关键字具体执行了哪些操作?
举例来说。
var Kimy = new Student();
new 关键字主要执行三项操作。
var Kimy = {};
Kimy.__proto__ = Student.prototype;
Student.call(Kimy);
1、创建一个空对象。
2、设置该对象的原型。
3、初始化对象属性。
由此可以理解,为什么 Kimy.__proto__ 指向 Student.prototype(二者为同一引用),关键在于 new 关键字在背后起到了决定性作用。
以上为本文全部内容,希望能对大家有所帮助。