JS中的构造函数与类

39 阅读1分钟

构造函数:可以构造对象的函数,用以下代码逐步学习:

 

//代码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