当前位置: 首页 > article >正文

JavaScript 创建对象的8种方式?

1. Object 构造函数

创建自定义对象可以创建 Object 的一个新实例,再添加属性和方法。

let person = new Object();

// 添加属性
person.name = "lili";

// 添加方法
person.sayName = function() {
  console.log(this.name)
}

2. 对象字面量

使用{}来创建对象

let person = {
  name: "lili",
  sayName() {
    console.log(this.name)
  }
}

3. Object.create()

Object.create()方法创建一个新的对象,使用现有的对象作为新创建对象的原型.

let person = {
  name: "lili",
  sayName() {
    console.log(this.name)
  }
}

let person1 = Object.create(person);
console.log(person1.name); // "lili"

4. 类(ES)

类用于创建对象的模版,它建立在原型上。
使用类声明来创建一个对象:

class Person {
  constructor(name) {
    this.name = name;
  }
	// 定义方法
  sayName() {
    console.log(this.name)
  }
}

const person1 = new Person("lili");
person1.sayName(); // "lili"

使用类表达式来创建一个对象:

let Person = class {
  constructor(name) {
    this.name = name;
  }
	// 定义方法
  sayName() {
    console.log(this.name)
  }
}

const person1 = new Person("lili");
person1.sayName(); // "lili"

注意:函数声明和类声明的一个重要区别是:函数声明会提升,类声明不会。

🔆为什么函数声明会有变量提升?
因为 JavaScript 的执行分为了编译阶段执行阶段,在编译阶段,js 引擎 执行任何代码之前创建一个 执行上下文,并为作用域内的所有变量分配内存空间.会先扫描整个作用域(即函数或全局作用域),并将所有通过 var 声明和函数声明的变量提升到顶部。

5. 工厂模式

用于抽象创建特定对象,在内部使用Object 构造函数来创建对象。
可以用不同的参数多次调用这个函数,每次都会返回包含相同属性和方法的对象,但缺点是没有给出新创建的对象的类型。

function createPerson(name) {
  let o = new Object();
  o.name = name;
  o.sayName = function() {
    console.log(this.name);
  };
  return o;
}

let person1 = createPerson("lili");
let person2 = createPerson("Joe");

6. 构造函数

构造函数是用于创建特定类型对象的

function Person(name) {
	this.name = name;
    this.sayName = function() {
        console.log(this.name)
    }
}

let person1 = new Person("lili");
let person2 = new Person("Joe");

person1.sayName(); // "lili"
person2.sayName(); // "Joe"

用 new 操作符调用构造函数会执行如下操作:

  1. 在内存中创建一个新对象
  2. 这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
  4. 执行构造函数内部的代码
  5. 如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象。
function newOperator(Constructor, ...args) {
  let thisValue = Object.create(Constructor.prototype);  // 对应上文操作步骤: 12
  let result = Constructor.apply(thisValue, args); // 对应上文操作步骤: 34
  return typeof result === 'object' && result !== null ? restult : thisValue; // 对应上文操作步骤: 5
}

// 测试代码
function Person(name) {
	this.name = name;
    this.sayName = function() {
        console.log(this.name)
    }
}

let person1 = newOperator(Person, "lili");
let person2 = newOperator(Person, "Joe");

person1.sayName(); // "lili"
person2.sayName(); // "Joe"

上文中创建的 person1 和 person2 都分别保存着 Person 的不同实例。这两个对象都有一个 constructor 属性指向 Person:

console.log(person1.constructor === Person) // true
console.log(person2.constructor === Person) // true

constructor 是用于标识对象类型的,instanceOf 操作符也可以确定对象类型。如下所示:

console.log(person1 instanceof Object);  // true
console.log(person1 instanceof Person);  // true

优点:可以确保实例被标识为特定类型,相比于工厂函数,这是一个很大的好处。
缺点:定义的方法在每个实例上都创建一遍。person1 和 person2 的都有名为 sayName() 的方法,但这两个方法不是同一个 Function 实例。ECMAScript 中的函数是对象,因此每次定义函数时,都会初始化一个对象。

7. 原型模式

每个函数都会创建一个 prototype 属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。

function Person() {};

// 将属性和方法添加到 prototype 属性上
Person.prototype.name = "Lucy";
Person.prototype.sayName = function() {
  console.log(this.name)
}

let person1 = new Person();
person1.sayName(); // "Lucy"

let person2 = new Person();
person2.sayName(); // "Lucy"

8. 组合模式

组合模式是原型模式构造函数模式的结合。

function Person(name) {
  this.name = name;
}

Person.prototype = {
  constructor: Person,
  sayName: function() {
    console.log(this.name)
  }
};

let person1 = new Person("Lucy");
let person2 = new Person("Joe");

person1.sayName(); //"Lucy"
person1.constructor === Person; // true

person2.sayName(); //"Joe"
person2.constructor === Person; // true

http://www.kler.cn/a/527159.html

相关文章:

  • 如何写美赛(MCM/ICM)论文中的Summary部分
  • 基于Django的Boss直聘IT岗位可视化分析系统的设计与实现
  • pytorch基于FastText实现词嵌入
  • Jason配置环境变量
  • 134.力扣刷题--加油站--滑动窗口
  • 解析“in the wild”——编程和生活中的俚语妙用
  • Git进阶之旅:tag 标签 IDEA 整合 Git
  • 算法总结-数组/字符串
  • Linux 五种IO模型总篇(阻塞IO、非阻塞IO、信号驱动IO、多路复用IO(select、poll、epoll)、异步IO)
  • 仿真设计|基于51单片机的温湿度及甲醛检测报警系统
  • OPENPPP2 —— VMUX_NET 多路复用原理剖析
  • DeepSeek R1功能设计涉及的几个关键词
  • 数据分析系列--⑥RapidMiner构建决策树(泰坦尼克号案例含数据)
  • Spring Boot基本项目结构
  • sizeof和strlen的对比与一些杂记
  • 【multi-agent-system】ubuntu24.04 安装uv python包管理器及安装依赖
  • Windows程序设计10:文件指针及目录的创建与删除
  • 【协议详解】卫星通信5G IoT NTN SIB33-NB 信令详解
  • CSS 图像、媒体和表单元素的样式化指南
  • 音视频多媒体编解码器基础-codec
  • windows部署deepseek之方法(The Method of Deploying DeepSeek on Windows)
  • mysql中in和exists的区别?
  • 晴,初三,年已过
  • CPU 100% 出现系统中断 怎么解决
  • appmatrix平台(一个汇集原创web APP的平台)服务规划
  • 网络安全实战指南:攻防技术与防御策略