JavaScript中new关键字详解:原型继承与执行机制
本文深入解析JavaScript中new关键字的实际作用与执行机制。通过具体代码示例,详细拆解new操作在创建对象、绑定原型链、执行构造函数及处理返回值时的完整流程,阐明其核心功能在于实现原型继承而非简单的实例创建。
JavaScript中new关键字详解:原型继承与执行机制
与其他高级编程语言类似,JavaScript也提供了new关键字。传统观念中,new通常用于创建类的实例,但在JavaScript这种万物皆对象的体系中,使用new的意义何在?实际上,JavaScript中的new并非单纯为了创建类的实例,其核心作用在于实现继承机制。下文将详细剖析JavaScript中new关键字的具体运作原理。
function Animal(name){
this.name = name;
}
Animal.color = "black";
Animal.prototype.say = function(){
console.log("I'm " + this.name);
};
var cat = new Animal("cat");
console.log(
cat.name, //cat
cat.height //undefined
);
cat.say(); //I'm cat
console.log(
Animal.name, //Animal
Animal.color //back
);
Animal.say(); //Animal.say is not a function
若能理解前文输出的结果,表明你对JavaScript中new关键字及this关键字的运行机制已有深入掌握,可直接跳过本文。
我们将通过解析具体代码示例,进一步加深你对JavaScript中new关键字及继承机制的理解。若对JavaScript中的this关键字尚不熟悉,建议先阅读相关教程:JS作用域和this关键字。
代码解读
一、代码解读
第1至3行代码定义了一个名为Animal的函数,并在该函数的this上下文中定义了属性name,其值取决于函数执行时传入的形参。
第4行代码在Animal函数对象本身(注意:函数也是对象)上定义了一个静态属性color,并将其赋值为字符串“black”。
第5至7行代码在Animal函数的原型对象prototype上定义了一个名为say()的方法,该方法用于输出this所指向的name属性值。
第8行代码使用new关键字创建了一个名为cat的新对象。
第10至14行代码中,cat对象尝试访问name和color属性,并调用say方法。
第16至20行代码中,Animal对象尝试访问name和color属性,并调用say方法。
重点解析
二、重点解析
第8行代码是整个示例的关键所在:
var cat = new Animal("cat");
JavaScript引擎在执行该语句时执行了多项内部操作,以下伪代码模拟了其工作流程:
var obj = {};
obj.__proto__ = Animal.prototype;
var result = Animal.call(obj,"cat");
return typeof result === 'obj'? result : obj;
(1)创建一个空对象obj;
(2)将obj的__proto__属性指向Animal的原型对象prototype,从而建立obj对象的原型链:obj->Animal.prototype->Object.prototype->null。
若对JavaScript原型链概念尚不熟悉,建议先阅读相关教程:JS原型和原型链。
(3)在obj对象的执行上下文中调用Animal函数,并传递参数“cat”。这相当于执行var result = obj.Animal("cat")。
执行完上述语句后,obj对象便产生了属性name,并赋值为“cat”。关于JavaScript中call方法的用法,建议阅读相关教程:JS的call和apply。
(4)检查第3步中函数的返回值。若无返回值或返回值不是对象类型,则返回obj作为新对象;否则,将返回值作为新对象返回。
了解new的运行机制后,我们知道cat实际上是过程(4)的返回值,因此我们对cat对象的认知可进一步补充:
cat的原型链结构为:obj->Animal.prototype->Object.prototype->null。
cat对象上新增了一个属性:name。
分析完cat对象的生成过程,我们再来查看输出结果:
cat.name -> 在过程(3)中,obj对象已生成name属性。因此,cat.name即对应这里的obj.name。
cat.color -> cat会先查找自身是否包含color属性,若未找到则沿原型链向上查找。在上述示例中,color仅在Animal对象上定义为静态属性,并未定义在其原型链上,因此无法找到。
cat.say -> cat会先查找自身是否包含say方法,若未找到则沿原型链向上查找。在上述示例中,我们在Animal的prototype上定义了say方法,因此能在原型链中找到该方法。
此外,在say方法中还访问了this.name,此时的this指向其调用者obj,因此输出的是obj.name的值。
对于Animal对象而言,它本身也是一个对象,因此在访问属性和方法时同样遵循上述查找规则,故:
Animal.color -> 返回“black”。
Animal.name -> 返回“Animal”。Animal先查找自身的name属性并找到,但需注意:此处的name并非我们自定义的name,而是函数对象内置的属性。
通常情况下,函数对象在创建时会内置name属性,并将函数名作为其值(仅适用于函数对象)。
Animal.say -> Animal在自身未找到say方法,会沿其原型链继续查找。那么,Animal的原型链结构是什么呢?

从调试结果可以看出:
Animal的原型链结构为:
因此,Animal的原型链上并未定义say方法。
综上所述,JavaScript的new关键字主要作用是实现继承。在上述示例中,cat对象在生成时便继承了Animal中定义的方法和属性,因此,从某种不严谨的角度看,cat不是Animal的实例,而是其子类。可能有人会想:既然cat是通过new生成的,那cat和Animal应该是同类型的。我认为,既然是父类与子类的关系,它们就不可能是同类型。不信,请看:

javascript 使用new关键字的区别
javascript 使用new关键字的区别
第一种方式使用new关键字以原型的方式将user对象暴露到window对象中
//one
var user = function(){
this.name="";
this.id="";
};
user.add = function(){
console.log("add");
};
user.delete = function(){
console.log("delete");
};
user.prototype = user;
window.user = new user();
第二种方式不使用new关键字直接将user对象暴露到window对象中
//two
var user = {
name:"",
id:""
};
user.add = function(){
console.log("add");
};
user.delete = function(){
console.log("delete");
};
window.user = user;
使用
<button onclick="user.add()">增加</button>
<button onclick="user.delete()">删除</button>
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
