原型笔记
- 1. Object.getOwnPropertyNames()
在學習使用該方法的時候,查閱了《JavaScript高級程序設計》與 MDN 來綜合學習。
先來看看MDN對其的表述:
參數
- 一個對象,其自身的可枚舉和不可枚舉屬性的名稱被返回。
obj:返回值
? 在給定對象上找到的屬性對應的字符串數組。
? 描述
Object.getOwnPropertyNames()?返回一個數組,該數組對元素是?obj自身擁有的枚舉或不可枚舉屬性名稱字符串。?數組中枚舉屬性的順序與通過?for...in?循環(或?Object.keys)迭代該對象屬性時一致。數組中不可枚舉屬性的順序未定義。
同時,舉出了幾個例子來表顯示,例如:
var arr = ["a", "b", "c"]; console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]// 類數組對象 var obj = { 0: "a", 1: "b", 2: "c"}; console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]// 使用Array.forEach輸出屬性名和屬性值 Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {console.log(val + " -> " + obj[val]); }); // 輸出 // 0 -> a // 1 -> b // 2 -> c//不可枚舉屬性 var my_obj = Object.create({}, {getFoo: {value: function() { return this.foo; },enumerable: false} }); my_obj.foo = 1;console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]
正如:MDN上所述,該方法返回的是對象自身的可枚舉與不可枚舉屬性,即返回的是一個數組。并且在查閱《JavaScript高級程序設計》這本書籍的時候,卻發現了一個問題。
function Person(){}
Person.prototype.name = 'asfd'
Person.prototype.age = 15
Person.prototype.sayName = function () {
console.log(this.name)
}
var keys = Object.getOwnPropertyNames(Person.prototype) console.log(keys)
// 書籍中表述keys返回的是 ['constructor', 'name', 'age', 'sayName']
// 但是當將Person.property設置一個以對象字面量形式創建的對象時,就不再返回constructor. 書籍中已經解釋此時的constructor不再指向Person // 于是,我真的操作了一遍才發現,真的如此
// 實例如下:
function Person(){ } Person.prototype = {name: 'zwj',age: 21,say: function () {console.log('say')} }
var keys = Object.getOwnPropertyNames(Person.property)
console.log(keys)
// 此時返回的 ['name','age','sayName']
我根據書中理解如下:設置一個以對象字面量形式創建的對象,雖然結果相同,但是constructor不再指向Person,這就涉及到原型鏈了
首先,每個構造函數被創建的時候,同時就創建了一個構造函數對應的原型對象,即: 構造函數.prototype?
這個對象就會自動獲得一個constructor屬性,這個屬性就是該對象指向構造函數的指針,你也可以試試輸出: Person.prototype? ? Person.prototype.constructor? ? ?Person.prototype.constructor.prototype 等等,就會發現形成了一個閉環...
這里我們使用的語法去接收屬性值,本質上默寫了prototype對象,這時候,改寫的對象默認的constructor指向為Object構造函數,畢竟函數也是對象,在JS中一切皆為對象...
所以如果我們通常為了在原型上進行大量的屬性寫入,就必須對這部分操作進行注意,需要在使用設置對象字面量方式之后手動為其添加constructor屬性的指向,這樣做的目的就是為了確保通過該屬性能夠訪問到適當的值...
當然你會覺得這樣設置并不是完美,畢竟對于constructor這個屬性,他應該是不可枚舉的,此時,卻是可枚舉的,這是就需要我們使用Object.defineProperty()進行相應的設置.相應的代碼如下:
function Person(){ } // 此時重寫了prototype對象 constructor指向Object Person.prototype = {name: 'Nick',age: 15,sayName: function(){consolelog(this.name)} } // 對constructor進行設置修改 Object.defineProperty(Person.prototype, 'constructor', {enumerable: false, // 設置是否可枚舉 false為不可枚舉value: Person // 設置值為Person }) //可以通過definePrototype進行更改數據屬性的共有6個,其余4個分別為: // configurable ----------> 表示是否可以通過delete進行刪除 默認為true // writable ----------> 表示是否可以修改屬性的值 默認為true
// get ----------> 一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認為 undefined。
// set --------> 一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。該方法將接受唯一參數,并將該參數的新值分配給該屬性。默認為 undefined。
總結: 在進行創建構造函數的時候,以前習慣只是將constructor直接寫在重寫的prototype對象中,但是卻忽略了其中最重要的一條信息,那就是constructor屬性本身是不可枚舉的屬性,還需要更深一層的操作去設置constructor.看問題不能只看表面,更應該注重于內在...
?
轉載于:https://www.cnblogs.com/gxlself/p/9121090.html
總結
- 上一篇: 同意好友
- 下一篇: 中国顶级黑客45秒使用声音来破坏您的计算