javascript
JS 总结之原型
在 JavaScript 中,函數也是屬于對象,可以像其他對象一樣訪問屬性,其中便有一個屬性叫原型 prototype,值為一個對象,默認,原型有一個 constructor 屬性,指向了構造函數本身。
function Person () {return 'hi' } Person.prototype // {constructor: ?} Person.prototype.constructor // ? Person() {} 復制代碼用圖來表示:
我們可以對這個屬性進行操作,但這個屬性,只有在對函數進行構造調用的時候才會起作用。
? 為原型添加屬性和方法
function Person (name) {this.name = name } Person.prototype.smart = true Person.prototype.run = function () {console.log('running') }// 或者一次性添加Person.prototype = {smart: true,run() {console.log('running')} } 復制代碼? 使用
訪問對象原型上的屬性和訪問對象的屬性的方式是一樣的:
// ... let a = new Person('a') a.name // a a.smart // true a.run() // running 復制代碼? instanceof
用來檢測構造函數的原型是否存在于實例的原型鏈上
// ... let b = new Person('b') b instanceof Person // true b instanceof Object // true 復制代碼? hasOwnPrototype
該方法來判斷是否自身屬性,如:
function Person () {this.name = 'Jon' } Person.prototype.name = 'people' Person.prototype.age = 18 let jon = new Person() jon.hasOwnProperty('name') // true jon.hasOwnProperty('age') // false 復制代碼age 為原型上的屬性,所以為 false。
? isPrototypeOf
該方法來判斷對象是否是另一個對象的原型,如:
let base = {name: 'people',age: 18 } function Person () {this.name = 'Jon' } Person.prototype = base let jon = new Person() base.isPrototypeOf(jon) // true 復制代碼? getPrototypeOf
當不知道對象的原型具體是哪個的時候,可以使用該方法來判斷,如:
let base = {name: 'people',age: 18 } function Person () {this.name = 'Jon' } Person.prototype = base let jon = new Person() Object.getPrototypeOf(jon) // { name: 'people', age: 18 } 復制代碼? _ _proto_ _
引用《MDN _ _proto_ _ 》 的解釋:
Object.prototype 的 _ _proto_ _ 屬性是一個訪問器屬性(一個 getter 函數和一個 setter 函數), 暴露了通過它訪問的對象的內部原型 (一個對象或 null)。
也就是說,每個對象都有一個該屬性,便攜訪問原型對象,直指原型對象:
let base = {name: 'people',age: 18 } function Person () {this.name = 'Jon' } Person.prototype = base let jon = new Person() jon.__proto__ // { name: 'people', age: 18 } 復制代碼用圖來表示:
與 prototype 不同的是,_ _proto_ _ 是對象的屬性,prototype 是構造函數的屬性。
?【ES5】Object.create(..)
該方法創建一個新對象,使用現有的對象來提供新創建的對象的 _ _proto_ _:
let base = {name: 'people',age: 18 } let jon = Object.create(base) jon.__proto__ // { name: 'people', age: 18 } 復制代碼? 原型鏈
當訪問對象的一個屬性時,js 引擎會遍歷自身對象的屬性,如果找不到,便會去原型上查找該屬性,如果還是找不到,便會繼續查找原型的屬性,直到到 Object 原型。
由于原型是一個對象,是對象便會有一個原型,有原型說明存在構造函數,如 Person 例子,查看原型的構造函數是啥:
// ... Person.prototype.__proto__.constructor // ? Object() { [native code] }Person.prototype.__proto__.constructor === Object // true 復制代碼說明 Object 是 Person 原型 的構造函數。
說明 Person 原型 的 _ _proto_ _ 會指向 Object.prototype,因為 _ _proto_ _ 能快捷訪問原型:
// ... Object.getPrototypeOf(jon.__proto__) === Object.prototype // true // 或者 jon.__proto__.__proto__ === Object.prototype // true // 或者 Person.prototype.__proto__ === Object.prototype // true 復制代碼用圖表示就是:
舉個例子:
// ... let a = new Person('a') a.toString() // "[object Object]" 復制代碼Person 函數和原型上都沒有 toString 方法,所以只能調用 Object 上的 toString 方法。
注意:基于同一個構造函數生成的對象,共享函數的原型,如:
// ... let b = new Person('b') b.name // b b.smart = false b.smart // false a.smart // false b.__proto__ === a.__proto__ // true 復制代碼對 b 的 smart 屬性進行修改,a 訪問 smart 也有原先的 true 變為 false 了。
? Object.prototype
Object.prototype.__proto__ // null 復制代碼null 是什么意思?此處無對象的意思,說明 Object.prototype 沒有原型,查到這里就停止查找了,如果在找不到目標屬性,就返回 undefined。
? 自身屬性優先
如果自身和原型上存在同名屬性,會優先使用自身屬性,例如:
function Person () {this.name = 'Jon' } Person.prototype.name = 'people' let jon = new Person() jon.name // Jon 復制代碼? 參考
- 《JavaScript 深入之從原型到原型鏈》 by 冴羽
- 《Object.create()》 by MDN
- 《_ _proto_ _ 》 by MDN
- 《JavaScript 面向對象編程指南(第 2 版)》第 5 章 原型
- 《Node.js 開發指南》附錄 A
轉載于:https://juejin.im/post/5c1d2b036fb9a049d9752feb
總結
- 上一篇: Windows下Oracle的下载与安装
- 下一篇: 探析“Java序列化”之serialVe