1.对象字面量(Object Literal)
用法: 直接通过{}定义对象,是最简单的方式;
原理: 直接分配内存创建一个普通对象,继承object.prototype;
- 直接内存分配: 当使用{}定义对象时,js引擎会直接在堆内存中分配一个普通对象。
- 隐藏原型继承: 该对象的[[Prototype]](即 proto) 会自动指向 Object.prototype, 继承原始对象默认方法 (如:toString).
- 属性初始化: 字面量中的属性和方法会直接挂载到对象自身,而非原型链。
例子:
const person { name: '小明', age: 25, greet() { console.log(`hi , i'm ${this.name}`) } } person.greet() //hi ,i'm 小明
const obj = {key:“value”}; //等价于: const obj = new Object(); //隐式调用 Object 构造函数 obj.key = "value";
特点:
- 适合创建单例对象或一次性对象;
- 所有属性方法均为实例自身成员,无法共享
2.构造函数(constructor function)
用法:通过 new 关键字调用构造函数创建对象
原理: new 操作
- 1.创建空对象: 在内存中创建一个新对象 {}
- 2.绑定原型:将新对象的[[Prototype]] 即原型链, 指向构造函数的prototype属性
- 3.执行构造函数:将构造函数内的this指向新对象,执行构造函数代码(初始化属性)
- 4.返回对象: 若构造函数未显示返回其他对象,则返回新对象;
例子:
function person(name, age){ // this = {}; (隐式操作) // this.__proto__ = person.prototype; (隐式操作) this.name = name; this.age = age; this.greet = function(){ console.log(`hi, i'm ${this.name}`) } // return this; (隐式操作) } const xiaoming = new person('小明', 25); xiaoming.greet(); //hi, i'm 小明 //原型链结构: xiaoming.__proto__ -> person.prototype -> Object.prototype -> null;
缺点:每个实例的方法都是独立的,浪费内存(可以优化共享原型方法);
- 若方法定义在构造函数内部,每个实例会有独立的方法副本(浪费内存);
- 若方法定义在person.prototype上,所有实例共享同一方法(推荐做法)
3. Object.create()
用法:基于现有对象作为原型创建新对象。
原理:创建一个新对象,并将其Prototype 指向传入的对象;
- 显式原型继承:直接创建一个新对象,并手动指定其[[Prototype]] 即:原型链 __ proto __
- 参数处理: 1.若传入null, 新对象的[[Prototype]]为null (无原型链); 2.若传入对象proto, 新对象继承proto的属性和方法;
例子:
const prototypeObj = { greet(){ console.log(`hi, i'm ${this.name}`) } } const person = Object.create(prototypeObj); person.name = "小明"; person.age = 10; person.greet(); //hi , i'm 小明
扩展:可创建无原型的对象(Object.create(null)),适合纯粹的数据存储;
4.工厂函数(Factory Function)
用法: 封装对象创建逻辑的函数,直接返回新对象;
原理:手动创建对象并返回,不依赖 new 或原型链;
- 封装对象创建: 通过普通函数返回新对象,不依赖new或者原型链。
- 独立实例: 每次调用工厂函数都会产生新的对象,所有属性和方法均为实例自身成员。
例子:
function createPeason(name,age){ const obj = {}; //显示创建对象 obj.name = name; obj.age = age; obj.greet = function(){} //方法不共享 return obj; } const xiaoming = createPeason('小明',10); xiaoming.greet(); //hi, i'm 小明;
特点:避免 new 的使用,但方法无法共享(每个实例的方法独立)。
对比构造函数:
- 优势: 更直观,避免new 的依赖。
- 劣势: 方法无法共享,内存效率低。 (因为是闭包啊)
5.ES6 class 语法
用法:使用clase关键字定义类,通过new实例化;
原理:本质是构造函数的语法糖(构造函数另一种写法),基于原型链实现继承。
- 方法挂载: 类中定义的方法会自动添加到prototype对象上,实现共享;
- 继承机制: extends 关键字通过修改原型链实现继承(子类的prototype 指向父类实例)
例子:
class Person { construtor(name,age){ this.name = name; this.age = age; } greet(){ console.log(`hi, i'm ${this.name}`) } } const xiaoming = new Person('小明',10); xiaoming.greet(); // hi, i'm 小明; //原型链结构: xiaoming.__proto__ -> Person.prototype -> Object.prototyle -> null;
优点: 语法更清晰,支持继承(extends)和静态方法(static)
6.单例模式(Singleton)
用法:确保一个类只有一个实例;
原理:通过闭包或模块化限制实例化次数
- 闭包封装: 通过立即执行函数(iife)和闭包保存唯一实例的引用。
- 惰性初始化: 在首次调用时创建实例,后续调用直接返回已存在的实例;
例子:
const singleton - (function(){ let instance; function createInstance() { return { id: Math.random() }; } return { getInstance(){ if(!instance) instance = createInstance(); return instance; } } })(); const obj1 = singleton.getInstance(); const obj2 = singleton.getInstance(); console.log(obj1 === obj2); //true
汇总 – 总结对比
方式 | 特点 | 适用场景 |
---|---|---|
对象字面量 | 简单直接,适合一次性对象 | 简单数据存储、配置项 |
构造函数 | 可复用,但方法定义在原型上 节省内存 | 需要多个相似实例 |
Object.create() | 灵活控制原型链,可创建无原型的对象 | 原型继承、纯净对象 |
工厂函数 | 避免 new, 但方法无法共享 | 简单对象生活 |
class | 语法清晰,支持继承 | 面向对象开发 |
单例模式 | 全局唯一实例 | 全局状态管理 |
选择建议:
- 简单对象: 优先用对象字面量或者工厂函数。
- 复用和继承: 使用class或构造函数。
- 原型控制: 使用Object.create()。
- 全局唯一: 单例模式。
以上就是JS创建对象的六种方式的详细内容,更多关于JS创建对象的资料请关注脚本之家其它相关文章!
来源链接:https://www.jb51.net/javascript/3392861ok.htm
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容