es6的對象屬性
Object.is()
用來比較兩個值是否嚴格相等,與嚴格比較運算符( === ) 的行爲基本一致
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
注意:: +0 不等於 -0 NaN等於自身
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign(a,b,c)
用於對象合併,將源對象(source)的所有可枚舉屬性,複製到目標對象( target )
a 是目標對象 b,c是源對象,也是就需要賦值的對象
注意: 如果目標對象與源對象有同名屬性,或者多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性
var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
如果只有一個參數,Object.assign()會直接返回這個參數
var obj = {a:1}
Object.assign(obj) === obj
如果該參數不是對象,則會先轉化成對象,然後返回
undefined 和 null 無法轉化成對象,所以用他們作爲參數,就會報錯,但是如果這非對象參數的位置在源對象中,就會跳過這些無法轉化的對象,因此不會報錯.如果在目標對象中,無法跳過,就一定報錯
其他類型的值( 即數值 ,字符串 和 布爾值 ) 不在首參數,也不會報錯,但是,除了字符串會以數組的形式拷貝到目標對象,其他值都不會產生效果,會被忽略.
var v1 = 'abc';
var v2 = true;
var v3 = 10;
var obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
Object.assign()拷貝的屬性是有限制的,只拷貝源對象的自身屬性( 不拷貝繼承屬性) ,也不拷貝不可枚舉的屬性
屬性名爲Symbol值的屬性,會被拷貝
注意: Object.assign() 方法實行的是淺拷貝, 如果遇到同名的屬性,會將其覆蓋起值
常見的用途:::
1: 爲對象添加屬性
將x
屬性和y
屬性添加到Point
類的對象實例
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
2: 爲對象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同於下面的寫法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};
3::: 克隆對象
將原始對象拷貝到一個空對象中,就能得到一個一模一樣的原始對象的克隆對象了
function clone(origin) {
return Object.assign({}, origin);
}
不過,採用這種克隆,只能克隆原始對象自身的值,不能克隆它繼承的值.如果想要保持繼承鏈,可以採用以下方式:
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
4::: 合併多個對象
將多個對象合併到某個對象中去,第一個參數爲目標對象,後面是源對象
const merge =
(target, ...sources) => Object.assign(target, ...sources);
如果希望合併後返回一個新對象,可以改寫上面函數,對一個空對象合併。
const merge =
(...sources) => Object.assign({}, ...sources);
5::: 爲屬性指定默認值
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
}
注意:: 存在深拷貝的問題
屬性的可枚舉性
對象的每個屬性都有一個描述對象,用來控制該屬性的行爲.
Object.getOwnPropertyDescriptor
方法可以獲取該屬性的描述對象。
描述對象的enumerable屬性,稱爲'可枚舉性',如果該屬性爲false,就表示某些操作會忽略當前屬性.
以下這幾個操作都會忽略enumerable屬性
for ...in :: 只會遍歷對象自身的和繼承的可枚舉的屬性
Object.keys() :: 返回對象自身的所有可枚舉的屬性的鍵名
JSON.stringify() :: 只串行對象自身的可枚舉的屬性
Object.assign) :: 只拷貝對象自身的可枚舉的屬性
另外,es6規定,所有的class的原型的方法都是不可枚舉的
屬性的遍歷
1:: for ... in 循環遍歷對象自身的和繼承的可枚舉屬性( 不包含symbol屬性 )
2:: Object.keys() 返回一個數組,包括對象自身的( 不含繼承的 ) 所有可枚舉的屬性( 不含symbol )
3:: Object.getOwnPropertyNames(obj) 返回一個數組,包括對象自身的所有屬性( 不含symbol屬性,但是包括不可枚舉屬性)
4:: Object.getOwnPropertySymbols(obj) 返回一個數組.包含對象自身的所有symbol屬性
5:: Reflect.ownKeys(obj) 返回一個數組,包含對象自身的所有屬性,不管是屬性名是symbol或者字符串.也不管是否可枚舉
以上的5種方法遍歷對象的屬性,都遵守同樣的屬性遍歷的次序規則。
- 首先遍歷所有屬性名爲數值的屬性,按照數字排序。
- 其次遍歷所有屬性名爲字符串的屬性,按照生成時間排序。
- 最後遍歷所有屬性名爲Symbol值的屬性,按照生成時間排序。
_proto_
如果一個對象本身部署了_proto_屬性,則該屬性的值就是對象的原型
_proto_屬性(前後各兩個下劃線) ,用來讀取或設置當前對象的prototype對象.
它的本質是一個內部屬性,並不是api,只是瀏覽器廣泛支持.而且只有瀏覽器必須部署這個屬性,其他運行環境不一定需要部署,而且新的代碼最好不要使用這個屬性,可以使用Object.setPrototypeOf() 寫操作 , Object.getPrototypeOf() 讀操作 , Object.create() 生成操作
在實現上,__proto__
調用的是Object.prototype.__proto__
,具體實現如下。
Object.defineProperty(Object.prototype, '__proto__', {
get() {
let _thisObj = Object(this);
return Object.getPrototypeOf(_thisObj);
},
set(proto) {
if (this === undefined || this === null) {
throw new TypeError();
}
if (!isObject(this)) {
return undefined;
}
if (!isObject(proto)) {
return undefined;
}
let status = Reflect.setPrototypeOf(this, proto);
if (!status) {
throw new TypeError();
}
},
});
function isObject(value) {
return Object(value) === value;
}
Object.setPrototypeOf()
用來設置一個對象的prototype對象
// 格式
Object.setPrototypeOf(object, prototype)
// 用法
var o = Object.setPrototypeOf({}, null);
function (obj, proto) {
obj.__proto__ = proto;
return obj;
}
Object.getPrototypeOf()
用來讀取一個對象的prototype對象
Object.getPrototypeOf(obj);
function Rectangle() {
}
var rec = new Rectangle();
Object.getPrototypeOf(rec) === Rectangle.prototype
// true
Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// false
Object.keys()
遍歷屬性的鍵名,返回一個數組,成員是參數對象自身的(不含繼承)所有可以遍歷的(enumerable)
var obj = { foo: "bar", baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
Object.values()
遍歷屬性的鍵值,返回一個數組,成員參數是對象自身的(不含繼承)所有可遍歷(enumerable)屬性的鍵值
var obj = { foo: "bar", baz: 42 };
Object.values(obj)
// ["bar", 42]
object.values()會過濾屬性名爲Symbol值的屬性,如果參數是一個字符串,會返回各個字符組成的一個數組
字符串會先轉化成一個類似數組的對象.字符串的每個字符,就是該對象的一個屬性.因此Object.values()
返回每個屬性的鍵值,就是各個字符組成的一個數組
如果參數不是對象,會先將其轉化成對象,由於數值和布爾值的包裝對象,都不會爲實例添加非繼承的屬性,會返回空數組
Object.values(42) // []
Object.values(true) // []
Object.entries()
遍歷屬性的鍵值對數組,返回一個數組,成員是參數對象自身的(不可繼承)所有可遍歷的屬性的鍵值對數組
忽略Symbol值的屬性
Object.entries方法的一個用處是,將對象轉爲真正的Map結構
var obj = { foo: 'bar', baz: 42 };
var map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }
對象的擴展運算符(...)
( 具體內容移步到es6-----數組的擴展中,鏈接:: https://mp.csdn.net/console/editor/html/104451458)
Object.getOwnPropertyDescriptors()
返回某個對象屬性的描述對象