JS 原型链

JS 原型链

若要建立两个汽车的实体,该如何建立?

Why use OO

减少重複的程式码减少记忆体的使用使实体有关联性

类别、物件

类别: 为实体的蓝图、範本 Ex:车子设计图物件: 透过类别建立出来的实体(instance) Ex:车子

原型链特性

JS prototype Base 继承方式最上层的原型为物件向上寻找属性、方法的特性继承特性 (不同实体,继承同一属性、方法)类别使用 new关键字 建造出实体

小建议

类别 使用大写作为开头 Car静态方法 使用_作为开头 static _add()使用 Object.getPrototypeOf(obj) 取得原型使用 ES6 Class使用 预设参数 & 解构

Level 0 (直接建立物件)

直接建立两个物件其缺点: 繁琐、无法统一管理、扩展性差、占用记忆体
  const carA = {    wheels: 4,    pressHorn() { console.log('AAA') },  }  const carB = {    wheels: 4,    pressHorn() { console.log('BBB') },  }

Level 1 (prototype建立蓝图)

利用 JS prototype 建立蓝图使用 new 关键字建立实体缺点: function功能相同,但每次创造实体时都複製一份,占用了不必要的记忆体
  // ES6 default parameter  const Car = function (brand, sound = '888') {    // ES5 预设变数写法    this.brand = brand !== undefined ? name : 'toyota'    this.wheels = 4    this.pressHorn = function () { console.log(sound) }    // 勿使用此做预设变数,遇到 falsy 会出错    this.test1 = test !! undefined ? test : '123'    this.test2 = test || '123'  }  const carA = new Car('AAA')  const carB = new Car('BBB', 'BBB')

Level 2 (在原型上建立共用方法)

将 Function 挂载到蓝图的 prototype利用原型链 向上寻找的特性,实体无该属性、方法即往上寻找可用的属性、方法写于原型仅佔一份记忆体
  Car.prototype.pressHorn = function () {    console.log(`${this.brand} ${this.sound}`)  }  // true 表 Function 来自同一个记忆体位置  console.log(carA).pressHorn() === carB.pressHorn())

Level 3 (ES5 Reveal Pattern)

封装内部资料,公开想公开的介面ES5 範例
  const Car = function (brand,sound) {    this.brand = brand    this.wheel = 4    return {      brand,    }  }  const test = new Car('A','AAA')  console.log(test.wheels) // undefined 不可取得  console.log(test.brand) // 可取得

Level 4 (ES6 Class)

JS 为 prototype base,因此 Class 仅为 prototype的语法糖使用 Class 使语法更精简
  class Car {    // 写于 constructor的内容,皆会在记忆体创一份新的    // 因此 方法避免写于 constructor 内部    constructor(brand = 'default') {      // constructor内容会于实体建立时执行      this.brand = brand      this.init()     }    init() { console.log('init') }    pressHorn(){      console.log(`${this.brand} ${this.sound}`)    }  }

Bonus: 预设参数 & 解构

  const User = function ({ name = 'default', age }) {    this.name = name // 可预设但可传入修改    this.age = age    this.gender = 'male' // 可预设不给用传入的  }  // 传入顺序无差,以 Key为基準  let test = new User({ age: 30 })  console.log(test.name, test.gender) // 'default' 'male'

取得原型语法

取得原型1: 双下底线proto (不推荐使用 效能差)取得原型2: Object.getPrototypeOf(obj) (建议使用、IE9+)
// ESLint/MDN 不建议使用 __proto__ 取得原型const CarProto = Car.__proto__// 推荐使用 ES5const CarProto = Object.getPrototypeOf(Car)

instanceof 原理 (判断是否有该原型)

判断目标是否在其原型链之下
  // 判断 'str' 是否在 String 之下  console.log('str' instanceof String)   // false,因为此种表示方法为原始型别,其原型链为 undefined  // 使用 new 关键字建立物件  const newStr = new String('newStr')  console.log(newStr instanceof String )  console.log(newStr instanceof Object )  // 皆true,String & Object 皆于 newStr 原型链上

参考资料

保哥 物件导向基础
偷米 ES6 Class介绍


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章