构造函数:可以构造对象的函数,用以下代码逐步学习:
//代码1//所有构造出来的Person对象都能sayHi
function Person(name='匿名', age=1) {
return {
name,
age,
sayHi: function() {
console.log(你好,我是${this.name})
}
}
}
const p = Person('frank', 18)
const p2 = Person('frank', 18)
p.sayHi()
p2.sayHi()
缺陷:每次调用Person都会生成一个新的匿名函数sayHi,造成内存冗余
//解决办法:把sayHi声明到外面,在赋值时用外面的sayHi
function sayHi(){
console.log(你好,我是${this.name})
}
function Person(name = '匿名', age = 1){
return {
name,
age,
sayHi
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p2.sayHi()
新要求:要求所有构造出来的Person对象都能run
//解决办法:加一个run
function sayHi(){
console.log(你好,我是${this.name})
}
function run(){
console.log(我会小跑)
}
function Person(name = '匿名', age = 1){
return {
name,
age,
sayHi,
run
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
缺点:全局变量名过多
//解决办法:把所有变量名集中到一个
const Person共有属性 = {
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
function Person(name = '匿名', age = 1){
return {
name,
age,
...Person共有属性
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
新要求:现在代码使用到了两个全局变量名(Person、Person共有属性),要求仅用一个
//解决办法:函数本身就是一个对象,直接把共有属性放在Person的一个属性上
function Person(name = '匿名', age = 1){
return {
name,
age,
sayHi: Person.共有属性.sayHi,
run: Person.共有属性.run
}
}
Person.共有属性 = {
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
新要求:要求使用原型(隐藏属性)减少内存冗余
//解决办法
function Person(name = '匿名', age = 1){
const temp = {} //临时对象
temp.proto = Person.共有属性
temp.name = name
temp.age = age
return temp
}
Person.共有属性 = {
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
缺陷:不符合代码标准,不允许使用__proto__
//解决办法
function Person(name = '匿名', age = 1){
const temp = Object.create(Person.共有属性) //以x为隐藏属性的值构造一个空对象
temp.name = name
temp.age = age
return temp
}
Person.共有属性 = {
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
提问:p1是谁构造出来的
//解决办法:在共有属性里面添加一个constructor
function Person(name = '匿名', age = 1){
const temp = Object.create(Person.共有属性) //以x为隐藏属性的值构造一个空对象
temp.name = name
temp.age = age
return temp
}
Person.共有属性 = {
constructor: Person,
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
const p1 = Person('jack',10)
const p2 = Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
console.dir(p1)
if(p1.constructor === Person){
console.log(你是个人类,不是Object实例,也不是Array实例)
}
js之父说,以上的操作不用再自己写了,我已经把它内置到js上去了
//解决办法,使用this、new
function Person(name = '匿名', age = 1){
this.name = name
this.age = age
}
Person.prototype = {
constructor: Person,
sayHi(){
console.log(你好,我是${this.name})
},
run(){
console.log(我会小跑)
}
}
const p1 = new Person('jack',10)
const p2 = new Person('luo',10)
p1.sayHi()
p1.run()
p2.sayHi()
p2.run()
console.dir(p1)
if(p1.constructor === Person){
console.log(你是个人类,不是Object实例,也不是Array实例)
}
用new的好处:
1、 帮你创建一个新对象
2、 帮你准备Person.共有属性
3、 帮你关联隐藏属性与共有属性
4、 帮你return新对象
5、 帮你加constructor
但java说:我要使用class
//解决办法:使用class
class Person {
constructor(name = '匿名',age = 1){
this.name = name
this.age = age
}
sayHi (){
console.log(你好,我是${this.name})
}
run (){
console.log(我会小跑)
}
}
const p1 = new Person('frank',18)
console.dir(p1)
缺点:class做不到共有一个非函数属性,需要用到static