javascript
javascript --- 对象原型
對象原型
參考 - MDN
Javascript中的原型
在Javascript中,每一個函數都有一個特殊的屬性,叫做原型
下面獲取函數的原型fn.prototype
function f1(){} console.log(f1.prototype) /*{constructor: f f1()__proto__:{constructor: f Object()__defineGetter__: f __defineGetter__()__defineSetter__: f __defineSetter__()hasOwnProperty: f hasOwnProperty()__lookupGetter__: f __lookupGetter__()__lookupSetter__: f __lookupSetter__()isPrototypeOf: f isPrototypeOf()...}} */下面給函數的原型添加屬性fn.prototype.hello = 'world'
function f1(){} f1.prototype.hello = 'world' console.log(f1.prototype) /*{hello: "world"constructor: f f1()__proto__: Object} */創建一個函數的實例new fn(),并給實例添加屬性
function Person(){} Person.prototype.hello = 'world' var p1 = new Person() p1.say = 'hi' console.log(p1) /*{say: "Hi"__proto__:{hello: "world"constructor: f Person()__proto__: Object}} */瀏覽器訪問某個屬性的尋找順序:
- 首先會尋找這個實例是否含有該屬性
- 如果有則返回,否則會通過__proto__尋找該實例的原型Person.prototype上是否含有該屬性.
- 如果有則返回,否則會通過__proto__.__proto__的上尋找該屬性.
- 如此循環.到最后__proto__.__proto__. ... = undefined則返回undefined
理解原型對象
下面定義一個構造器函數
function Person(first, last, age, gender, interests){this.first = firstthis.last = lastthis.age = agethis.gender = genderthis.interests = interests } var p1 = new Person("Li","Bruce",18,'男','coding') console.log(p1.__proto__ === Person.prototype) // true console.log(p1.__proto__.__proto__ === Object.prototype) // true console.log(p1) /*{first: "Li"last: "Bruce"age: 18gender: "男"interests: "coding"__proto__:{constructor: f Person(first, last, age, gender, interests)__proto__:{constructor: f Object()__defineGetter__: f __defineGetter__()...valueOf: f valueOf()...}}} */- 此時存在一條原型鏈:
此時,調用如下:
p1.valueOf()根據前面的規則:
- 瀏覽器首先檢查,p1對象是否含有valueOf()方法
- 如果沒有,則瀏覽器檢查p1對象的原型對象(Person.prototype, 通過瀏覽器提供的__proto__訪問)是否具有可用的valueOf()方法
- 如果還沒有,瀏覽器會檢查Person()構造函數的prototype屬性所指向的對象的原型對象(Object.prototype)是否含有該方法,如果有則返回,否則返回undefined
原型鏈中的方法和屬性沒有被復制到其他對象 – 它們被訪問需要通過"原型鏈"的方式
官方并未提供__proto__屬性,在JavaScript語言標準中用[[prototype]]表示.然而,大多數現代瀏覽器還是提供了一個名為__proto__的屬性.
prototype屬性: 繼承成員被定義的地方
查看MDN - Object可以看到,Object有很多屬性,但是在上面的p1中,并不是全部都繼承了.
原因在于: 被繼承的屬性僅僅只是定義在Object.prototype上的屬性.定義在Object本身上的屬性是不會被繼承的
看下面的栗子:
function Person(){} console.log(Person.prototype) /*{constructor: f Person()__proto__: Object} */默認情況下,構造器(此處為Person)的prototype屬性初始為空白.
靜態成員與實例成員
- 靜態成員: 在構造函數本身上添加的成員
- 實例成員: 構造函數內部通過this添加的成員,只能通過實例化的對象來訪問
使用prototype的好處
節約內存.例如下述:
function Person(name, age){this.name = namethis.age = agethis.sayHi = function(){console.log('Hi ~')} } var p1 = new Person('Mar', 18) var p2 = new Person('Marron', 19)上面通過構造函數,生成了2個實例化對象,但是兩個實例化對象的方法的內存地址是不同的.
console.log(p1.sayHi == p2.sayHi) // false引用prototype屬性可以節約內存
function Person(name, age){this.name = namethis.age = age } Person.prototype.sayHi = function(){console.log('Hi ~') } var p1 = new Person('Mar', 18) var p2 = new Person('Marron', 19) console.log(p1.sayHi == p2.sayHi) // true p1.sayHi() // "Hi ~"-
可見構造函數通過Person.prototype類似構造的所有對象是共享的(同一個內存空間)
-
javascript規定,每一個構造函數都有一個prototype屬性,指向另一個對象.
總結
以上是生活随笔為你收集整理的javascript --- 对象原型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IAR软件学习
- 下一篇: javascript --- vue2