news 2026/4/18 5:22:28

JS构造函数与原型链详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JS构造函数与原型链详解

一、构造函数(完整代码示例)

构造函数就是一个普通函数,创建方式和普通函数没有区别,不同的是首字母习惯上大写。构造函数和普通函数的区别就是调用方式不同 普通函数直接调用fun(),构造函数需要使用new关键字来调用(var per=new Person();)

1. 构造函数与普通函数的区别(调用方式)
// 1. 普通函数(首字母小写,直接调用) function sayHello() { console.log("普通函数调用"); this.name = "普通函数"; // 非严格模式下this指向window } // 普通调用 sayHello(); // 输出:普通函数调用 console.log(window.name); // 输出:普通函数(验证this指向) // 2. 构造函数(首字母大写,new调用) function Person(name, age) { // 执行流程: // 1. 隐式创建新对象;2. this指向新对象;3. 执行代码;4. 返回新对象 this.name = name; this.age = age; this.sayHi = function() { console.log(`我是${this.name},今年${this.age}岁`); }; } // 构造函数调用(创建实例) const per1 = new Person("张三", 20); const per2 = new Person("李四", 22); console.log(per1); // 输出:Person { name: '张三', age: 20, sayHi: [Function] } per1.sayHi(); // 输出:我是张三,今年20岁 per2.sayHi(); // 输出:我是李四,今年22岁 // 3. instanceof检查实例归属 console.log(per1 instanceof Person); // 输出:true(per1是Person的实例) console.log(per1 instanceof Object); // 输出:true(所有对象都是Object的后代) console.log(per1 instanceof Array); // 输出:false(验证非Array实例)

构造函数的执行流程:

1、立刻创建一个新的对象

2、将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象

3、逐行执行构造函数中的代码

4、将新创建的对象作为返回值返回

使用同一个构造函数创建的对象属于同一类对象,我们也将一个构造函数称为一个类。通过一个构造函数创建的对象,称为该类的实例,也称为该构造函数的实例。

使用instanceof可以检查一个对象是否是一个类的实例

所有对象都是Object的后代

二、原型(prototype)(完整代码示例)

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,叫原型对象,每个函数都有,都指向一个不同的原型对象。

如果函数作为普通函数调用,prototype没有任何作用;如果函数以构造函数形式调用时,它所创建的对象中都会有一个隐含的属性__proto__,指向该构造函数的原型对象,我们可以通过__proto__访问该属性。

原型对象就相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象。我们可以将对象中共有的内容,统一设置到原型对象中。这样不用分别为每一个实例对象添加,也不会影响到全局作用域,就可以使每个对象中都有这些属性和方法。

1. 原型对象的基本使用(公共属性 / 方法)
// 构造函数 function Student(name, score) { this.name = name; // 实例自身属性 this.score = score; } // 原型对象添加公共方法(所有实例共享) Student.prototype.sayScore = function() { console.log(`${this.name}的成绩是${this.score}分`); }; // 原型对象添加公共属性 Student.prototype.school = "第一中学"; // 创建实例 const stu1 = new Student("小明", 90); const stu2 = new Student("小红", 85); // 访问实例自身属性 console.log(stu1.name); // 输出:小明(自身属性) // 访问原型对象的属性/方法 console.log(stu1.school); // 输出:第一中学(原型属性) stu2.sayScore(); // 输出:小红的成绩是85分(原型方法) // 验证:所有实例共享原型方法(内存复用) console.log(stu1.sayScore === stu2.sayScore); // 输出:true
2. 属性查找规则(自身 → 原型 → 原型的原型)

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,有直接使用,如果没有会去原型对象中找,如果找到则直接使用

// 接上面的Student构造函数 // 1. 自身有属性,优先使用自身 stu1.score = 95; console.log(stu1.score); // 输出:95(自身覆盖原型) // 2. 自身无,找原型;原型无,找原型的原型;直到Object原型(null) console.log(stu1.toString()); // 输出:[object Object](来自Object.prototype) console.log(stu1.abc); // 输出:undefined(最终未找到)
3. in 与 hasOwnProperty 区别

使用in检查对象中是否含有某个属性时,如果对象中没有但是原型对象中有,也会返回true;

使用对象的hasOwnProperty("name"),检查对象自身中是否含有该属性,只有对象自身中有时才会返回true。

// 接上面的stu1实例 // 1. in:自身或原型有则返回true console.log("name" in stu1); // 输出:true(自身有) console.log("school" in stu1); // 输出:true(原型有) console.log("toString" in stu1); // 输出:true(Object原型有) // 2. hasOwnProperty:仅自身有则返回true console.log(stu1.hasOwnProperty("name")); // 输出:true(自身有) console.log(stu1.hasOwnProperty("school")); // 输出:false(原型有) console.log(stu1.hasOwnProperty("toString")); // 输出:false(Object原型有)
4. 原型链示例(多层原型查找)
// 自定义构造函数 function Animal(type) { this.type = type; } // Animal原型添加方法 Animal.prototype.eat = function() { console.log(`${this.type}会吃东西`); }; // Dog继承Animal(简化版,仅演示原型链) function Dog(name) { this.name = name; } // 将Dog的原型指向Animal的实例(形成原型链) Dog.prototype = new Animal("狗"); // 创建Dog实例 const dog1 = new Dog("旺财"); // 原型链查找: // dog1自身 → Dog.prototype(Animal实例) → Animal.prototype → Object.prototype → null console.log(dog1.name); // 自身:旺财 dog1.eat(); // Animal.prototype:狗会吃东西 console.log(dog1.toString()); // Object.prototype:[object Object] console.log(dog1.xxx); // 输出:undefined(最终未找到)

三、完整整合示例(构造函数 + 原型 + 原型链)

原型对象也是对象,所以它也有原型。当我们使用一个对象的属性或方法时,会先在自身中寻找。自身中如果有,直接使用;如果没有则去原型对象中找,如果原型对象中有,则直接使用;如果没有则去原型对象中的原型去找,直到找到Object对象的原型。Object对象的原型没有原型(对应的值为null),如果还没有找到则返回undefined。

// 1. 定义构造函数 function Car(brand, color) { // 实例自身属性 this.brand = brand; this.color = color; } // 2. 原型添加公共方法(所有Car实例共享) Car.prototype.run = function() { console.log(`${this.color}的${this.brand}正在行驶`); }; // 原型添加公共属性 Car.prototype.wheels = 4; // 3. 创建实例 const car1 = new Car("宝马", "白色"); const car2 = new Car("奔驰", "黑色"); // 4. 访问属性/方法 console.log(car1.brand); // 自身:白色 console.log(car1.wheels); // 原型:4 car2.run(); // 原型方法:黑色的奔驰正在行驶 // 5. 检查属性归属 console.log("wheels" in car1); // true(原型有) console.log(car1.hasOwnProperty("wheels")); // false(自身无) console.log(car1.hasOwnProperty("brand")); // true(自身有) // 6. 原型链验证 console.log(car1.__proto__ === Car.prototype); // true(实例的__proto__指向构造函数原型) console.log(Car.prototype.__proto__ === Object.prototype); // true(原型的原型指向Object原型) console.log(Object.prototype.__proto__); // null(Object原型无原型)

四、核心总结

  1. 构造函数通过new调用,自动创建 / 返回对象,this指向实例;
  2. 原型(prototype)是构造函数的属性,存储实例共享的属性 / 方法,减少内存占用;
  3. 属性查找遵循「自身 → 原型 → 原型链」规则,直到Object.prototype.__proto__(null);
  4. in检查整个原型链,hasOwnProperty仅检查实例自身。




版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 1:02:24

5分钟精通智能提取工具:告别繁琐操作的高效指南

还在为频繁切换网页查找提取码而烦恼吗?智能提取工具的出现彻底改变了这一现状,让资源获取变得前所未有的简单高效。这款工具专为提升工作效率而生,通过自动化处理复杂查询流程,帮助用户一键获取所需信息,大幅减少操作…

作者头像 李华
网站建设 2026/4/17 13:36:22

基于Springboot午托管理系统的设计与实现588oe817(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。

一、系统程序文件列表 二、开题报告内容 基于Spring Boot午托管理系统的设计与实现开题报告 一、选题背景及意义 选题背景 随着社会经济的发展和城市化进程的加快,双职工家庭数量日益增多,家长因工作繁忙无法在中午时段照顾孩子,午托服务…

作者头像 李华
网站建设 2026/4/18 3:14:25

WindowsCleaner:5分钟彻底解决C盘爆红的终极方案

WindowsCleaner:5分钟彻底解决C盘爆红的终极方案 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否也遇到过这样的情况:C盘突然变红&a…

作者头像 李华
网站建设 2026/4/18 3:16:12

小红书数据采集:5个关键步骤让你轻松获取精准营销数据

在数字化营销时代,小红书已成为品牌洞察消费者需求的重要窗口。xhs工具作为专为小红书数据采集设计的Python库,为营销人员、数据分析师和内容创作者提供了高效的数据获取方案。这款基于小红书Web端进行请求封装的工具,让数据采集变得简单可靠…

作者头像 李华
网站建设 2026/4/18 3:14:24

英伟达开源发布最新AI模型!引入突破性专家混合架构,推理性能超越Qwen3和GPT,百万token上下文,模型数据集全开源!

Nemotron 3 支持 1M token 的上下文窗口,使模型能够在大型代码库、长文档、延展式对话以及聚合检索内容之上进行持续推理。与依赖碎片化分块启发式方法不同,智能体可以将完整的证据集合、历史缓冲区和多阶段规划全部保留在单一上下文窗口中。 就在刚刚&…

作者头像 李华