1. 程式人生 > 資訊 >阿里本地生活,為何「起大早,趕了晚集」?

阿里本地生活,為何「起大早,趕了晚集」?

210316

物件建立模式

1、Object建構函式模式
  • 套路:先建立空的object物件,在動態新增屬性/方法
  • 適用場景:起始時不確定物件內部資料
  • 問題:語句太多
var p = new Object()
p.name = 'tom'
p.age = 12
p.setName = function(name){
    this.name = name
}
//測試
p.setName('jack')
console.log(p)
2、物件字面量模式
  • 使用{}建立物件,同時指定屬性/方法
  • 使用場景:起始時物件內部資料是確定
  • 問題:如果建立多個物件,有重複程式碼
var p = {
    name : 'tom',
    age : 12,
    setName : function(name){
        this.name = name
    }
}
console.log(p.name, p.age)
p.setName("jack")
console.log(p.name, p.age)
3、工廠模式
  • 通過工廠函式(返回一個物件的函式)建立物件並返回
  • 適用場景:要建立多個物件
  • 問題:物件沒有一個具體的型別,都是Object型別
function createPerson(name,age){
    var obj = {
        name : name,
        age : age,
        setName : function(name){
            this.name = name
        }
    }
    return obj //返回一個物件的函式===》工廠函式
}

var p1 = createPerson('tom',12)
console.log(p1)
var p2 = createPerson('bob',13)//object

function Dog(name,price){
    var obj2 = {
        name: name,
        price: price
    }
    return obj2
}
var d = Dog("hashiqi",1000)//object
console.log(d instanceof Object)

4、自定義建構函式模式
  • 自定義建構函式,通過new建立物件
  • 適用場景:需要建立多個型別確定的物件
  • 問題:每個物件都有相同的資料,浪費記憶體
function Person(name,age){
    this.name = name
    this.age = age
    this.setName = function(name){
        this.name = name
    }
}
var p1 = new Person('tom',12)
console.log(p1 instanceof Person) //true

function Dog(name,price){
    this.name = name
    this.price = price
}
var d = new Dog('hashiqi',1000)
console.log(d instanceof Dog)  //true
5、建構函式+原型的組合模式
  • 自定義建構函式,屬性在函式中初始化,方法新增到原型上
  • 適用場景:需要建立多個型別確定的物件
function Person(name,age){
    this.name = name
    this.age = age
}
Person.prototype.setName = function(name){
    this.name = name
}
var p1 = new Person('tom',12)
var p2 = new Person('bob',20)
console.log(p1,p2)

繼承模式

1、原型鏈繼承
  • 套路

    • 定義父型別建構函式

    • 給父型別的原型新增方法

    • 定義子型別的建構函式

    • 建立父型別的物件賦給子型別的原型(子型別的原型指向父型別例項)

      Child.prototype = new Parent()

    • 將子型別原型的構造屬性(constructor)設定為子型別

      Child.prototype.constructor = Child

    • 給子型別原型新增方法

    • 建立子型別的物件:可以呼叫父型別的方法

  • 關鍵

    • 子型別的原型為父型別的一個例項物件
//父型別
function Supper(){
    this.supProp = 'Supper property'
}
Supper.prototype.showSupperProp = function(){
    console.log(this.supProp)
}

//子型別
function Sub(){
    this.subProp = 'Sub property'
}

//例項物件能呼叫object原型上的方法sub.toString()
//子型別的原型為父型別的一個例項物件
Sub.prototype = new Supper()
//讓子型別的原型的constructor指向子型別
//constructor是原型物件的屬性
console.log(sub)
Sub.prototype.constructor = Sub
Sub.prototype.showSubProp = function(){
    console.log(this.subProp)
}

var sub = new Sub() 
sub.showSupperProp()
sub.showSubProp()
console.log(sub)
2、借用建構函式繼承(假的)
  • 套路
    • 定義父型別建構函式
    • 定義子型別建構函式
    • 在子型別建構函式中呼叫父型別構造
  • 關鍵
    • 在子型別建構函式中呼叫通用call()呼叫父型別建構函式
function Person(name,age){
    this.name = name
    this.age = age
}
function Student(name,age,price){
    //通過call呼叫person並改變this的指向
    Person.call(this,name,age)//相當於:this.Person(name,age)
    this.price = price
}
var s = new Student('tom',12,10000)
console.log(s.name,s.age,s.price)
3、組合繼承

原型鏈+借用建構函式的組合繼承

  • 利用原型鏈實現對父型別物件的方法繼承
  • 利用super()借用父型別建構函式初始化相同屬性
function Person(name,age){
    this.name = name
    this.age = age
}
Person.prototype.setName = function(name){
    this.name = name
}
function Student(name,age,price){
    //通過call呼叫person並改變this的指向
    Person.call(this,name,age)
    this.price = price
}
Student.prototype = new Person()//為了看到父型別的方法
Student.prototype.constructor = Student//修正constructor屬性
Student.prototype.setPrice = function(price){
    this.price = price
}
var s = new Student('tom',12,10000)
s.setName('bob')
s.setPrice(17000)
console.log(s.name,s.age,s.price)
  • new一個物件背後做了什麼?
    • 建立一個空物件
    • 給物件設定____proto__,值為建構函式物件的prototype屬性值(this.__proto = Fn.prototype)
    • 執行建構函式體(給物件新增屬性/方法)