距离上次的你不知道 Combo 有段时间了,这次要端出的是营养更 up up 的满汉全席原型系列,包括原型、继承、constructor、class 等,今天先从 constructor 讲起
本文可学到:
Constructor 中文译为「 建构子 」或者是 「 建构式 」,从名称可以理解应该是要 「建构」也就是创造出什麽,没错,在 JS 内可以透过 constructor 制造出结构类似的物件,用鸡蛋糕比喻的话,constructor 就是模具,可以依照不同的模具制造出大量相同形状的鸡蛋糕。
从倒入面糊加热完成到产生一个鸡蛋糕,正式一点的名称会说,实体化一个物件,产生出来的物件就称为该建构子的实例 instance。
JavaScript 有内建好的鸡蛋糕模具,但也可以设计自己想要的模具,这种模具就称为 建构式函式 constructor function,加上关键字 new
就可以来做鸡蛋糕罗!
new
+ constructor function
既然叫 constructor function,模具就是透过 function 做出来的,直接实作一个看看
// 做一个名为 RabbitCake 的模具
function RabbitCake(flavor) {
this.producer = 'Hooo';
this.shape = 'rabbit';
this.flavor = flavor;
}
let rabbit1 = new RabbitCake('cream');
let rabbit2 = new RabbitCake('chocolate');
定义一个名为 RabbitCake 的模具,希望做出来的每个鸡蛋糕都印有三个资讯,制作者: Hoo、形状: rabbit、口味:个别指定。
模具好了就可以来做鸡蛋糕罗,依照食谱说的要用 new
+ 模具名称,参数放想要的口味,第一个 rabbit1 是奶油口味,第二个 rabbit2 是巧克力口味。
印出 rabbit1 和 rabbit2 看看成功了吗?
console.log(rabbit1) // RabbitCake {producer: "Hooo", shape: "rabbit", flavor: "cream"}
console.log(rabbit2) // RabbitCake {producer: "Hooo", shape: "rabbit", flavor: "chocolate"}
成功! 两个鸡蛋糕内都有我们需要的资讯
input 到 output 中间的过程发生了什麽事,继续往下深究吧
仔细看程序码,发现其实 RabbitCake 就是个普通的 function,没有回传值出去,照理来说赋值到变数上应该印出 undefined
呀
let rabbit3 = RabbitCake('cream')
console.log(rabbit3) // undefined
但上面印出的 rabbit1 是个含有三个属性的物件,中间花生什麽事?
其实是关键字 new
发挥作用啦
new
时, 会先有一个空物件被建立在 RabbitCake 内加上 console.log(this)
来看看新物件属性一个个创建的过程
function RabbitCake(flavor) {
console.log(this) // 一开始被创建的空物件
this.producer = 'Hooo';
console.log(this) // 加入第一个属性 producer
this.shape = 'rabbit';
console.log(this) // 加入第二个属性 shape
this.flavor = flavor;
console.log(this) // 加上最後一个属性 flavor,值来自参数
}
let rabbit1 = new RabbitCake('cream');
整理一下使用建构式函式的重点
new
关键字来创造物件,因此给了特别的名称function RabbitCake(flavor) {
this.producer = 'Hooo';
this.shape = 'rabbit';
this.flavor = flavor;
return {};
}
let rabbit1 = new RabbitCake('cream');
console.log(rabbit1) // {}
前面提到 JavaScript 有做好的鸡蛋糕模具,他们在哪呢?存在全域物件下
打开浏览器的开发者工具,输入 window 可以看到全域物件的所有属性,根据 ECMA 19.3 中列出来的 constructor 有 40 种!
可以发现这些 constructor 都是 function 以大写开头,昨天学到的 Math 是物件所以不是 constructor 唷!
各大型别也算在内,加上 new
关键字後可以创造物件,而本身是 function 也可以呼叫
// 作为 function 呼叫
String() // string
Number() // number
Boolean() // boolean
Date() // string
Array() // object
Object() // object
Function() // function
// 加上new 作为constructor呼叫
new String() // object
new Number() // object
new Boolean // object
new Date() // object
new Array() // object
new Object() // object
new Function() // function
其实不建议对基本型别 constructor 使用 new
关键字,因为创出来的都是物件型别,如果能用字面值 literal 表达,就无需动用到 constructor 啦!
在查找 ECMA 时,对於其中描述 Array()、Function() constructor 这两段很困惑
also creates and initializes a new Array when called as a function rather than as a constructor. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.
creates and initializes a new function object when called as a function rather than as a constructor. Thus the function call Function(…) is equivalent to the object creation expression new Function(…) with the same arguments. - 20.2.1 The Function Constructor
原文意思是当 Array
作为一个 function 而不是 constructor 呼叫时,会建立并初始化一个新的阵列,因此当带入的参数相同时,使用 Array()
呼叫和作为 constructor呼叫 new Array()
是一样结果。 (Function 翻译亦同)
来实验看看
// 呼叫 Array as a function
let arr = Array(3).fill('Hi')
console.log(arr) // ['Hi', 'Hi', 'Hi']
// 呼叫 Array as a constructor
let brr = new Array(3).fill('Hi')
console.log(brr) // ['Hi', 'Hi', 'Hi']
// 呼叫 Function as a function
let afun = Function('a', 'b', 'return a+b')
console.log(afun(2,3)) // 5;
console.log(afun) // function(a, b) { return a+b}
// 呼叫 Function as a constructor
let bfun = new Function('a', 'b', 'return a+b')
console.log(bfun(2,3)) // 5
console.log(bfun) // function(a, b) { return a+b}
真的欸,使用 Array()、Function() 都是建立出一个新的阵列或函式,与加上 new关键字产生的结果是相同的!
了解建构子如何创建物件後,下一章来讲讲 this 到底是谁
ECMA
W3Schools
Constructor, operator "new"
建构物件范本:Constructor Function
[笔记] 谈谈 JavaScript 中内建的 function constructors 及应注意的地方
>>: 【Day 13】Google Apps Script - API 篇 - Drive Service - 云端硬碟服务范例
282. Expression Add Operators https://leetcode.com...
其实订阅订单跟定期定额作法非常相似, 这边会额外拉出来讲是因为个人对於他们两兄弟有不同定义, 文章是...
设计大纲 上一个区块设计了使用者的「痛点」,因此接下来的区块想要做一个「平台的小广告」,让使用者了解...
从单元测试探讨 MVC to MVVM 的差异 你在这里学到什麽? 用 RxSwift DataBi...
Web API -- Application Programming Interface for ...