摘要:一切對象都是的實例,一切函數都是的實例,是構造函數,函數是的實例,是對象,對象是的實例,可以說與是一對密不可分的兄弟,讓我們一起解開與的神秘面紗,本章主要了解相關知識,下章再來看構造函數可以創建一個對象包裝器中所有對象都來自所有對象從繼承方
一切對象都是 Object 的實例,一切函數都是 Function 的實例,Object 是構造函數,函數是 Function 的實例,Function.prototype 是對象,對象是 Object 的實例,可以說 Object 與 Function 是一對密不可分的兄弟,讓我們一起解開 Object 與 Function 的神秘面紗,本章主要了解 Object 相關知識,下章再來看 Function
Function instanceof Object // true Object instanceof Function // true
Object 構造函數可以創建一個對象包裝器
JS 中所有對象都來自 Object, 所有對象從 Object.prototype 繼承方法和屬性
傳入的值為 null 或 undefined 將返回一個 {} 空對象
Object(null) // {} Object(undefined) // {}
Object() 等同于 new Object()
對象字面量由 {} 包含零個或多個鍵值對組成以逗號分隔的列表構成
對象字面量是屬性名及其關聯值的集合
必須由 逗號 分隔
下面是 ES6(ECMAScript 2015) 中對象的定義方式
const a = 1; var obj = { a, get a(){}, set a(){}, ["a" + "b"]: "hello", say(){}, baz: { b: 2 } }重復屬性
重復的屬性,后面的屬性會覆蓋前面的屬性,在ES5中,重復的屬性會拋出語法錯誤 SyntaxError
對象合并Object.assign() 可以合并兩個對象,也可以使用展開符 ... 合并兩個對象,Object.assign() 會觸發 setter,而展開操作符則不會
var a = { a: 1 }; var b = { b: 2 }; var mergedObj = Object.assign({}, a, b) var mergedObj = { ...a, ...b }變更對象原型
如果給對象的 _proto_ 賦值為 null, 則會更改對象原型,賦值為其它任何值則不會改變對象原型
Object.getPrototypeOf({__proto__:null}) === null // true Object.getPrototypeOf({__proto__:{}}) === null // false
在對象字面值中,只有一次改變原型的機會,多次變更會報語法錯誤
不使用 : 定義 _proto__ 不會變更原型,而是會變成對象的普通屬性
var __proto__ = "variable"; var obj1 = { __proto__ }; Object.getPrototypeOf(obj1) === Object.prototype // true var obj2 = { __proto__() { return "hello"; } }; obj2.__proto__() === "與JSON區別
對象字面量 與 JSON(JavaScript Object Notation) 的區別
JSON 只允許 以 "property": value 的形式定義屬性,且屬性名必須以 " 號括起來,屬性定義不允許簡寫 JSON 中的屬性值只允許 字符串、數字、數組、true、false、null或其它JSON對象 JSON 中屬性值不允許是函數 JSON.parse() 不會處理計算屬性名,會拋語法錯誤Object.length
返回 Object() 構造函數形參數量,值為 1
Object.prototype Object.prototype.hasOwnProperty()檢查對象自身中是否有某屬性(忽略原型鏈中的屬性)
Object.prototype.isPrototypeOf()檢查當前原型是否在指定對象的原型中 (作用等同于 instanceof)
Object.prototype.propertyIsEnumerable()判斷屬性是否可枚舉
Object.prototype.toLocaleString()返回對象的字符串表示(用于派生對象重載)
Array.prototype.toLocaleString([locales[,options]]) Number.prototype.toLocaleString([locales[,options]]) Date.prototype.toLocaleString([locales[,options]])
新的 locales 和 options 參數讓應用程序可以指定要進行格式轉換的語言,并且定制函數的行為
在舊的實現中,會忽略 locales 和 options 參數,使用的語言環境和返回的字符串的形式完全取決于實現方式。
locales 和 options 不同的瀏覽器及版本有兼容性問題,所以這個api并沒有得到廣泛的應用
var prices = ["¥7", 500, 8123, 12]; prices.toLocaleString("ja-JP", { style: "currency", currency: "JPY" }); // "¥7,¥500,¥8,123,¥12" const num = 2333333; num.toLocaleString("zh", { style: "decimal" }); //2,333,333 num.toLocaleString("zh", { style: "percent" }); //233,333,300% const num = 2333333; num.toLocaleString("zh", { style: "currency", currency: "CNY" }); //¥2,333,333.00 num.toLocaleString("zh", { style: "currency", currency: "cny", currencyDisplay: "code" }); //CNY2,333,333.00 let num = 2333.3; num.toLocaleString("zh", { minimumIntegerDigits: 5 }); //02,333.3 //如果不想有分隔符,可以指定useGrouping為false num.toLocaleString("zh", { minimumIntegerDigits: 5, useGrouping: false }); //02333.3 num.toLocaleString("zh", { minimumFractionDigits: 2, useGrouping: false }); //2333.30 num = 666.666 num.toLocaleString("zh", { maximumFractionDigits: 2, useGrouping: false }); //666.67Object.prototype.toString()
返回對象的字符串表示
使用 toString 來檢查對象類型
function isNull(){
Object.prototype.toString.call(obj) === "[object Null]"
}
返回一個表示該對象的字符串
Object.assign()將可枚舉的屬性從一個或多個源拷貝到目標對象
但是只能深拷貝非嵌套的對象,嵌套屬性為淺拷貝
簡單的深拷貝
JSON.parse(JSON.stringify(Obj)), 缺點是會破壞對象的原型鏈,并且會丟失對象的方法
Object.create(proto, [propsObj])使用指定的原型創建對象
// ES5實現 (不支持 propsObj) function extend(proto){ function F(){}; F.prototype = proto; return new F(); } // 創建一個原型為null的空對象 var o = Object.create(null) var o = {} // 相當于 var o = Object.create(Object.prototype) // 為所創建的對象添加屬性 (如果缺省配置,默認為false) var o = Object.create(Object.prototype, { foo: { writeable: true, configurable: true, enumerable: true, value: "hello" } }) function MyClass (){} var o = new MyClass() // 相當于 var o = Object.create(Myclass.prototype)
Object.assign 只會拷貝源對象自身且可枚舉的屬性,會調用 源對象的 get 和 目標對象的 set 方法,
如果源對象的屬性 get 方法是自定義的,合并后,將會丟失
合并時,不會跳過那些值為 null 或 undefined 的源對象
Ojbect.assign 的ES5中的 polyfill
Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { "use strict"; if (target == null) { throw new TypeError("Connot convert undefined or null to object"); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index] for (var nextKey in nextSource) { if(Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } return to; }, writeable: true, configurable: true, })Object.defineProperty(obj, prop, descriptor)
定義或修改屬性對象
obj: 要定義屬性的對象 prop: 屬性名稱 descriptor: 屬性描述
屬性描述 descriptor 分為兩種:數據描述符 和 存取描述符
數據描述符:一個有值的屬性,可配置 是否可枚舉、是否可配置、是否可賦值 及 value值
存取描述符:有 getter、setter 函數的屬性,也可配置 是否可配置及是否可枚舉 屬性描述只能是 數據描述 或 存取描述 中的一種
數據描述符 描述的屬性只可能有 configurable、enumerable、writeable、value
存取描述符 描述的屬性只可能有 get、set、configurable、enumerable 四個配置 如果一個描述符不具有value,writable,get 和 set 任意一個關鍵字,那么它將被認為是一個數據描述符 // 數據描述符 描述的屬性 Object.defineProperty({}, "a", { // 是否可枚舉 決定了是否可被 for...in 和 Object.keys() 獲取屬性名 enumerabel: true, // 屬性描述是否可改變,該屬性是否可刪除,當前配置為false時,不能在數據和訪問器屬性類型之間切換,不可刪除,除 writable 之外的描述不可修改 configurable: true, // 是否可賦值 writeable: true, // 屬性值,默認為 undefined value: 1 }) // 存取描述符 描述的屬性 var bValue; Object.defineProperty({}, "b", { get: function(){ return value; }, set: function(newValue){ bValue = newValue }, enumerable: true, configurable: true, }) function Archiver () { var temp = null; var history = [] Object.defineProperty(this, "temp", { get: function () { console.log("get") return temp; }, set: function (newV) { temp = newV history.push({val: temp}) } }) this.getHistory = function(){ return history; }; } var arc = new Archiver() arc.temp arc.temp = 11 arc.temp = 13 arc.getHistory() // [{ val: 11 }, { val: 13 }]Object.defineProperties(obj, props)
定義或修改多個屬性對象 與 Object.defineProperty 一樣
var obj = {}; Object.defineProperties(obj, { "property1": { value: true, writable: true }, "property2": { value: "Hello", writable: false } });Object.entries()
返回可枚舉屬性的鍵值對數組
// 獲取 const obj = { foo: "bar", baz: 42 }; console.log(Object.entries(obj)); // [ ["foo", "bar"], ["baz", 42] ] // 遍歷 for...of const obj = { a: 5, b: 7, c: 9}; for(const [key, value] of Object.entries(obj)) { console.log(`${key} ${value}`); } // 遍歷 forEach Object.entries(obj).forEach(([key, value]) => { console.log(`${key} ${value}`); // "a 5", "b 7", "c 9" }); // Object 轉 Map new Map(Object.entries(obj))Object.freeze()
凍結一個對象,被凍結的對象,不可添加、刪除、修改其屬性,也不可修改屬性的描述配置,返回被凍結的對象
只能凍結對象中的第一層的常量對象,不可凍結復雜對象
obj1 = { internal: {} }; Object.freeze(obj1); obj1.internal.a = "aValue"; obj1.internal.a // "aValue" 自定義一個深凍結函數 function deepFreeze(obj){ const propNames = Object.getOwnPropertyNames(obj); propNames.forEach(name => { const prop = obj[name]; if(typeof prop === "object" && prop !== null) { deepFreeze(prop) } }) return Object.freeze(obj) }Object.isFrozen()
返回指定對象是否是凍結對象
Object.seal()封閉一個對象,對象屬性不可刪除,不可增加新屬性,不可修改屬性描述配置,但 可以修改屬性值
const object1 = { property1: 42 }; Object.seal(object1); object1.property1 = 33; console.log(object1.property1); // expected output: 33 delete object1.property1; // cannot delete when sealed console.log(object1.property1); // expected output: 33 Object.isSealed()
返回指定對象是否是封閉對象
獲取對象自身可枚舉的屬性
Object.keys()與 for...in 不同的是:for...in 還會遍歷對象原型鏈中的屬性
使用 for...in 獲取對象自身可枚舉的屬性
for(key in obj) { obj.hasOwnProperty(key){ console.log(key) } }Object.values()
返回可枚舉的屬性數組
const obj = { foo: "bar", baz: 42 }; console.log(Object.entries(obj)); // [ ["foo", "bar"], ["baz", 42] ]Object.getOwnPropertyNames()
獲取對象自身的屬性 (枚舉&不能枚舉)
獲取對象自身不可枚舉的屬性?
var allProps = Object.getOwnPropertyNames(obj) var enumProps = Object.keys(obj) var noenumProps = allProps.filter(v => enumProps.indexOf(v) === -1)Object.getOwnPropertySymbols()
返回對象自身所有 Symbol 屬性數組
對象自身屬性 包含了兩種類型,一種是 字符串屬性,一種是 Symbol 數據屬性,
字符串屬性名可由 Object.getOwnPropertyNames() 來獲取
Symbol 屬性名可由 Ojbect.getOwnPropertySymbols() 來獲取
默認對象是不含有 Symbol 屬性的,除非手動添加了 Symbol 屬性
返回 對象自身屬性的 描述配置信息
Object.getOwnPropertyDescriptors()返回 對象自身所有屬性的 描述配置信息
屬性描述分為兩種:存取描述 與 數據描述
var o = { get foo() { return 17; } }; var d = Object.getOwnPropertyDescriptor(o, "foo"); // d { // configurable: true, // enumerable: true, // get: /*the getter function*/, // set: undefined // } var o = { bar: 42 }; var d = Object.getOwnPropertyDescriptor(o, "bar"); // d { // configurable: true, // enumerable: true, // value: 42, // writable: true // }
Object.assign() 無法拷貝源對象屬性的特性,且屬性描述會被轉為數據描述,也無法拷貝源對象的原型
使用 Object.create() 可以完整的淺拷貝一個對象
Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj))Object.getPrototypeOf()
返回指定對象的原型
var proto = {}; var obj = Object.create(proto); Object.getPrototypeOf(obj) === proto; // trueObject.setPrototypeOf()
設置指定對象的原型
這個方法是ES6中的方法,用于替換ES5中 Object.prototype.__proto__ = newProto 的方式修改原型
修改原型對于瀏覽器是一個耗性能的方法,應避免去修改原型,使用 Object.create() 去創建新的對象
Object.is()同值相等比較 比較兩個值是否相等
與抽象相等 == 區別:
同值相等不會去隱式轉換數據類型
與嚴格相等 === 區別:
同值相告對于 -0與+0 返回 false, 而嚴格相等返回 true
對于 NaN 與 NaN,同值相等返回 true, 嚴格相等返回 false
Object.is(0, -0); // false Object.is(-0, -0); // true Object.is(NaN, 0/0); // true 0 === -0 //true +0 === -0 //true NaN === NaN //falseObject.isExtensible()
判斷指定對象是否可以擴展 (是否可以添加屬性及原型)返回 Boolean
var empty = {}; Object.isExtensible(empty); // === trueObject.preventExtensions()
禁止對象擴展 已有的屬性可以修改、刪除,但不能再添加新的屬性
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96649.html
摘要:它不區分該屬性是對象自身的屬性,還是繼承的屬性。那么我們要遍歷對象所有屬性,包括繼承以及不可遍歷的屬性,用加原型遍歷實現類似的用遞歸 Object靜態方法 Object自身方法,必須由Object調用,實例對象并不能調用 Object.getPrototypeOf() 作用是獲取目標對象的原型 function F() {}; var obj = new F(); console.lo...
摘要:原型鏈與繼承當談到繼承時,只有一種結構對象。如果對該圖不怎么理解,不要著急,繼續往下看基于原型鏈的繼承對象是動態的屬性包指其自己的屬性。當使用操作符來作用這個函數時,它就可以被稱為構造方法構造函數。 原型鏈與繼承 當談到繼承時,JavaScript 只有一種結構:對象。每個實例對象(object )都有一個私有屬性(稱之為proto)指向它的原型對象(prototype)。該原型對象也...
摘要:今天,就我們就來一步步解析響應式的原理,并且來實現一個簡單的。當然,這個也只是一個簡單的,來說明響應式的原理,真實的源碼會更加復雜,因為加了很多其他邏輯。接下來我可能會將其與聯系起來,實現和語法。 從很久之前就已經接觸過了angularjs了,當時就已經了解到,angularjs是通過臟檢查來實現數據監測以及頁面更新渲染。之后,再接觸了vue.js,當時也一度很好奇vue.js是如何監...
摘要:對象與屬性讓我們保持耐心,再梳理一下對象與屬性的關系對象是屬性的集合,當對象的屬性是函數時,我們將其稱之為方法。 這篇博文的主要目的是為了填坑,很久之前我發表了一篇名為關于JavaScript對象中的一切(一) — 對象屬性的文章,想要談一談JavaScript對象,可那時只是貼了一張關于這個主題的思維導圖,今天我會針對這一主題進行展開,將JavaScript對象一些平常不太常用的知識...
閱讀 1709·2021-11-18 10:02
閱讀 2222·2021-11-15 11:38
閱讀 2671·2019-08-30 15:52
閱讀 2195·2019-08-29 14:04
閱讀 3235·2019-08-29 12:29
閱讀 2090·2019-08-26 11:44
閱讀 997·2019-08-26 10:28
閱讀 836·2019-08-23 18:37