[ES6] js创建对象的几种方法 字面式创建对象 工厂模式 构造函数模式 prototype __ proto __ 对象访问机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ES6] js创建对象的几种方法 字面式创建对象 工厂模式 构造函数模式 prototype __ proto __ 对象访问机制相关的知识,希望对你有一定的参考价值。


字面式创建对象

var obj = 
let o1 =
name: Jack,
age: 18,
gender: 男


// 当我需要第二个对象的时候
let o2 =
name: Rose,
age: 20,
gender: 女

在使用同一接口创建多个对象时,会产生大量重复代码,为了解决此问题,工厂模式被开发

工厂模式

// 1. 创建一个工厂函数
function createObj(name, age, gender)
// 1-1. 手动创建一个对象
let obj =

// 1-2. 手动添加成员
obj.name = name
obj.name = age
obj.gender = gender

// 1-3. 手动返回这个对象
return obj


// 2. 使用工厂函数创建对象
// 创建第一个对象
let o1 = createObj(Jack, 18, 男)
console.log(o1)

// 创建第二个对象
let o2 = createObj(Rose, 20, 女)
console.log(o2)

工厂模式问题:

  • 创建对象 return对象 是 两个重复的冗余的操作
  • 创建的 实例化对象中 只是 属性中的属性值不同 函数方法完全相同,相同的函数方法也是 冗余的代码

构造函数模式

// 1. 创建一个构造函数
function createObj(name, age, gender)
// 1-1. 自动创建一个对象

// 1-2. 手动向对象上添加内容
this.name = name
this.age = age
this.gender = gender

// 1-3. 自动返回这个对象


// 2. 创建对象
let o1 = new createObj(Jack, 18, 男) // 本次调用的时候, 函数内部的 this 就指向 o1
console.log(o1)

// let o2 = createObj(Rose, 20, 女) // undefined, 因为没有关键字 new , 构造函数里不自动返回对象, 即没有创造对象的能力

let o2 = new createObj(Rose, 20, 女)
console.log(o2)

[ES6]


构建函数推荐首字母大写

=> 直观, 区别普通函数

=> 看到首字母大写的函数, 基本上就要和 new 连用

构造函数是否合理

function Person(name)
this.name = name
this.sayHi = function a() console.log(你好 世界)


let p1 = new Person(张三) // 本次创建的时候, 会开辟一段内存空间, 存储 a 函数
let p2 = new Person(李四) // 本次创建的时候, 会开辟一段内存空间, 存储 a 函数
  • 一旦在构造函数体内书写方法的时候
  • 你创建多少个实例化对象, 那么就有多少个方法要占用内存空间
  • 不合理: 因为会有多余的函数内存空间被占用

[ES6]


怎么解决呢?

我们要借助三个知识点 prototype 和 __ proto __ 和对象访问机制

prototype (原型 / 原型对象)

  • 定义: 每一个函数天生自带一个属性叫做 prototype, 他是一个对象
  • 只要函数定义好以后, 这个 prototype 就出生了
  • 构造函数也是函数, 构造函数也有 prototype, 我们可以向里面添加一些内容
  • 这个天生自带的 prototype 里面有一个属性叫做 constructor
    => 表示我是哪一个构造函数伴生的原型对象
function Person()

// 向 prototype 添加一些些属性和方法
Person.prototype.sayHi = function() console.log(hello world)

console.log(Person.prototype)

[ES6]

[ES6]

__ proto __

  • 定义: 每一个对象天生自带一个属性, 叫做__proto__, 指向所属构造函数的 ​prototype​
  • 实例化对象也是一个对象
  • 实例化对象也有​​__proto__​​属性
function Person()

Person.prototype.sayHi = function() console.log(hello world)

let p1 = new Person()
console.log(p1)

[ES6]

function Person()

Person.prototype.sayHi = function() console.log(hello world)

let p1 = new Person()
console.log(p1)

// 当我访问 p1.__proto__ 的时候就应该有 sayHi
console.log(Person.prototype, Person.prototype)
console.log(p1.__proto__, p1.__proto__)
console.log(Person.prototype === p1.__proto__) // true

[ES6]

[ES6]

怎么将​​prototype​​​ 和 ​​__ proto __​​运用到构造函数的合理性上呢?

对象访问机制

  • 当你访问一个对象的成员的时候
  • 如果对象自己本身有, 直接返回结果给你, 停止查询
  • 如果对象自己本身没有, 会自动去 proto 上访问
  • 有就给你返回结果, 停止查询
  • 如果还没有(未完待续)

利用 ​​prototype​​​, ​​__proto__​​和对象访问机制

  • 解决了构造函数的不合理
  • 属性直接写在构造函数体内
  • 方法书写在构造函数的 prototype 上
  • 使用构造函数创建一个 有属性 有方法 合理的 对象
  • prototype 的作用: 就是为了书写一些方法给该构造函数的实例对象使用的
    => 因为这个构造函数的每一个实例都可以访问这个构造函数的 prototype
function Person(name, age)
this.name = name
this.age = age


Person.prototype.sayHi = function() console.log(hello world)

// 使用 Person 创建一个对象
let p1 = new Person(Jack, 18)
console.log(p1)

// 当我访问 p1.name 的时候, 自己就有
console.log(p1.name)
// 当我访问 p1.sayHi 的时候, 自己没有
// 就去 p1.__proto__ 上找, 因为 p1.__proto__ === Person.prototype
// 实际上就是去 Person.prototype 上找
// 找到 sayHi
p1.sayHi()


// 再次创建一个实例化对象
let p2 = new Person(Rose, 20)

// 当我访问 p2.sayHi 的时候
// 因为自己没有, 去到 p2.__proto__ 上找
// 实际上也是去 Person.prototype 上找
p2.sayHi()

[ES6]

  • 当我访问 ​​p1.name​​ 的时候, 自己就有
  • 访问 p1.sayHi 的时候, 自己没有, 就去 ​​p1.__proto__​​​上找, 因为
    ​​p1.__proto__ === Person.prototype, 实际上就是去 ​​Person.prototype​​​ 上找 ​​sayHi​

由此可见, 调用同样的一个 sayHi 函数只占了一个函数内存空间
这样, 通过利用 prototype, proto 和对象访问机制, 使我们的构造函数变得合理

[ES6]

构造函数相关的 this 指向

  1. 构造函数体内的 this 指向
    => 因为和 new 关键字连用, this 指向当前实例
  2. 构造函数原型上的方法里面的 this 指向
    => 因为方法是依靠实例对象在调用
    => this 指向当前实例
function Person()
this.name = Jack
console.log(构造函数体内 : , this)


Person.prototype.fn = function()
console.log(我是Person.prototype 上的 fn 方法)
console.log(Person.prototype.fn : , this)


// 创建实例
let p1 = new Person()

console.log(===========)

// 调用方法
// fn 是 Person.prototype 上的方法
// 但是调用是依靠当前实例在调用
// 标准的对象调用方式
// p1.fn() this 点前面是谁就是谁
p1.fn() // this => 当前实例

[ES6]







以上是关于[ES6] js创建对象的几种方法 字面式创建对象 工厂模式 构造函数模式 prototype __ proto __ 对象访问机制的主要内容,如果未能解决你的问题,请参考以下文章

JS面向对象篇创建对象的几种方法

JavaScript的几种常见的创建方式

js-JavaScript常见的创建对象的几种方式

js-JavaScript常见的创建对象的几种方式

JS创建对象的几种方式详解

JS创建对象的几种方式整理