看完你就知道JavaScript 中的对象创建与继承方式原来这么简单?!

在 JavaScript 编程中,对象 是核心概念之一。理解如何创建对象以及如何实现对象之间的继承关系,对于掌握 JavaScript 面向对象编程至关重要。

本文将从两个部分来讲解:

  1. JavaScript 中对象的创建方式
  2. JavaScript 中对象的继承方式

我们会结合代码示例和生活中的类比,帮助你更好地理解这些看似晦涩的概念。


一、JavaScript 中对象的创建方式

1. 字面量方式(Object Literal)

这是最常见、最简单的方式。

js 复制代码
const person = {
    name: "张三",
    age: 25,
    sayHello: function() {
        console.log("你好,我是" + this.name);
    }
};

person.sayHello(); // 输出:你好,我是张三

2. 构造函数方式(Constructor Function)

通过定义一个构造函数,使用 new 关键字来创建多个相似对象。

js 复制代码
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayHello = function() {
        console.log("你好,我是" + this.name);
    };
}

const p1 = new Person("李四", 30);
p1.sayHello(); // 输出:你好,我是李四

生活类比:

这就像工厂流水线生产产品。构造函数就是生产线模板,每次调用 new 就像是启动一次生产,产出一个具有相同结构的产品(对象)。

3. 工厂函数方式(Factory Function)

不使用 new,而是返回一个新对象的函数。

js 复制代码
function createPerson(name, age) {
    return {
        name: name,
        age: age,
        sayHello: function() {
            console.log("你好,我是" + this.name);
        }
    };
}

const p2 = createPerson("王五", 28);
p2.sayHello(); // 输出:你好,我是王五

4. 使用 Object.create() 方法

这个方法允许你基于一个现有对象创建新对象。

js 复制代码
const personPrototype = {
    sayHello: function() {
        console.log("你好,我是" + this.name);
    }
};

const p3 = Object.create(personPrototype);
p3.name = "赵六";
p3.sayHello(); // 输出:你好,我是赵六

生活类比:

这就像你模仿某个成功人士的行为模式(原型),然后你自己也具备了类似的能力,但你也可以有自己的个性(属性)。


5. ES6 类语法(Class)

ES6 引入了类语法,让面向对象编程更接近传统语言如 Java/C++。

js 复制代码
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    sayHello() {
        console.log("你好,我是" + this.name);
    }
}

const p4 = new Person("小明", 20);
p4.sayHello(); // 输出:你好,我是小明

二、JavaScript 中对象的继承方式

JavaScript 的继承机制不同于传统的类继承语言(如 Java),它是一种基于原型(prototype-based)的语言。下面介绍几种常见的继承方式。


1. 原型链继承(Prototype Chaining)

通过将子类的原型指向父类的一个实例,从而实现继承。

js 复制代码
function Animal() {
    this.eat = function() {
        console.log("动物会吃东西");
    };
}

function Dog() {
    this.bark = function() {
        console.log("汪汪叫");
    };
}

Dog.prototype = new Animal(); // 继承Animal

const dog = new Dog();
dog.eat();  // 输出:动物会吃东西
dog.bark(); // 输出:汪汪叫

生活类比:

这就像孩子继承了父母的某些特征。比如你爸爸会游泳,你也可能会游泳;但你还有自己的技能,比如打篮球。


2. 构造函数继承(Classic Inheritance / Constructor Borrowing)

通过在子类构造函数中调用父类构造函数,实现对父类属性的继承。

js 复制代码
function Animal(name) {
    this.name = name;
}

function Dog(name, breed) {
    Animal.call(this, name); // 调用父类构造函数
    this.breed = breed;
}

const myDog = new Dog("旺财", "金毛");
console.log(myDog.name);   // 输出:旺财
console.log(myDog.breed);  // 输出:金毛

生活类比:

这就像你在注册公司的时候,先借用了一个已有的营业执照(父类构造函数),然后再添加自己的特色业务(子类属性)。


3. 组合继承(Hybrid Inheritance)

结合原型链继承和构造函数继承的优点。

js 复制代码
function Animal(name) {
    this.name = name;
}

Animal.prototype.eat = function() {
    console.log(this.name + " 在吃东西");
};

function Dog(name, breed) {
    Animal.call(this, name); // 构造函数继承
    this.breed = breed;
}

Dog.prototype = new Animal(); // 原型链继承
Dog.prototype.constructor = Dog;// 将被覆盖掉的constructor重新声明为Dog

Dog.prototype.bark = function() {
    console.log("汪汪!");
};

const d = new Dog("小白", "哈士奇");
d.eat();   // 输出:小白 在吃东西
d.bark();  // 输出:汪汪!

生活类比:

这就像你既继承了家族的传统手艺(原型链),又拥有自己的独特能力(构造函数),成为一个全能型选手。


4. 寄生组合式继承(Parasitic Combination Inheritance)

优化版的组合继承,避免了多次调用父类构造函数的问题。

js 复制代码
function inherit(subType, superType) {
    const prototype = Object.create(superType.prototype); // 创建对象
    prototype.constructor = subType; // 增强对象
    subType.prototype = prototype; // 指定对象
}

function Animal(name) {
    this.name = name;
}
Animal.prototype.eat = function() {
    console.log(this.name + " 在吃东西");
};

function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}

inherit(Dog, Animal);

Dog.prototype.bark = function() {
    console.log("汪汪!");
};

const d = new Dog("大黄", "土狗");
d.eat();   // 输出:大黄 在吃东西
d.bark();  // 输出:汪汪!

生活类比:

这就像是你找了一个中介(inherit 函数),帮你高效地继承家产(父类功能),而不是自己盲目操作,浪费资源。


5. ES6 类继承(Class Inheritance)

ES6 提供了 extendssuper 来简化继承。

js 复制代码
class Animal {
    constructor(name) {
        this.name = name;
    }

    eat() {
        console.log(`${this.name} 在吃东西`);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name); // 调用父类构造函数
        this.breed = breed;
    }

    bark() {
        console.log("汪汪!");
    }
}

const d = new Dog("豆豆", "柯基");
d.eat();   // 输出:豆豆 在吃东西
d.bark();  // 输出:汪汪!

总结对比表

创建方式 特点 适用场景
对象字面量 简洁直观 单个对象快速创建
构造函数 可复用,适合批量创建对象 多个相似对象
工厂函数 不依赖 new,封装性好 简单封装创建逻辑
Object.create() 明确指定原型 实现继承或共享行为
Class 类 语法清晰,符合传统OOP习惯 结构复杂项目
继承方式 特点 优缺点
原型链继承 简单易懂 共享引用类型数据风险
构造函数继承 属性独立 方法不能复用
组合继承 兼具两者优点 会执行两次父类构造函数
寄生组合继承 最优方案 稍复杂,需手动实现
Class 继承 语法简洁 ES6+ 支持,兼容旧环境可能受限

结语

JavaScript 的对象模型虽然不同于传统的类语言,但其灵活的原型机制赋予了强大的扩展能力。无论是创建对象还是实现继承,关键在于理解每种方式的原理和适用场景。

正如生活中我们学习他人经验、改进自己的做法一样,JavaScript 的对象也是通过继承不断丰富自身的能力。希望这篇文章能让你对 JavaScript 的对象有更清晰、深入的理解!

如果你喜欢这类内容,欢迎点赞收藏,后续我将持续更新更多前端进阶知识。

相关推荐
RadiumAg2 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo2 小时前
ES6笔记2
开发语言·前端·javascript
yanlele3 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
烛阴4 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
初遇你时动了情4 小时前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图
dssxyz4 小时前
uniapp打包微信小程序主包过大问题_uniapp 微信小程序时主包太大和vendor.js过大
javascript·微信小程序·uni-app
ohMyGod_1237 小时前
React16,17,18,19新特性更新对比
前端·javascript·react.js
@大迁世界7 小时前
第1章 React组件开发基础
前端·javascript·react.js·前端框架·ecmascript
一瓣橙子7 小时前
7.7日 实验03-Spark批处理开发(2)
开发语言·javascript·ajax
Hilaku7 小时前
从一个实战项目,看懂 `new DataTransfer()` 的三大妙用
前端·javascript·jquery