Object 靜態(tài)方法總結(jié)
create 創(chuàng)建一個(gè)對(duì)象
const obj = Object.create({a:1}, {b: {value: 2}})
第一個(gè)參數(shù)為對(duì)象,對(duì)象為函數(shù)調(diào)用之后返回新對(duì)象的原型對(duì)象,第二個(gè)參數(shù)為對(duì)象本身的實(shí)例方法(默認(rèn)不能修改,不能枚舉)
obj.__proto__.a === 1 // true
obj.b = 3;
console.log(obj.b) // 2
//創(chuàng)建一個(gè)可寫(xiě)的,可枚舉的,可配置的屬性p
obj2 = Object.create({}, {
p: {
value: 2, // 屬性值
writable: true, // 是否可以重寫(xiě)值
enumerable: true, //是否可枚舉
configurable: true //是否可以修改以上幾項(xiàng)配置
}
});
obj2.p = 3;
console.log(obj2.p) // 3
注意: enumerable 會(huì)影響以下
for…in 遍歷包括對(duì)象原型上屬性
Object.keys() 只能遍歷自身屬性
JSON.stringify 只能序列化自身屬性
defineProperty Object.defineProperty(object, prop, descriptor)定義對(duì)象屬性
添加數(shù)據(jù)屬性
var obj = {};
// 1.添加一個(gè)數(shù)據(jù)屬性
Object.defineProperty(obj, "newDataProperty", {
value: 101,
writable: true,
enumerable: true,
configurable: true
});
obj.newDataProperty // 101
// 2.修改數(shù)據(jù)屬性
Object.defineProperty(obj, "newDataProperty", {
writable:false
});
//添加訪問(wèn)器屬性
var obj = {};
Object.defineProperty(obj, "newAccessorProperty", {
set: function (x) {
this.otherProperty = x;
},
get: function () {
return this.otherProperty;
},
enumerable: true,
configurable: true
});
注意: 1.第一個(gè)參數(shù)必須為對(duì)象
2.descriptor 不能同時(shí)具有 (value 或 writable 特性)(get 或 set 特性)。
3.configurable 為false 時(shí),不能重新修改裝飾器
defineProperties Object.defineProperties(object, {prop1 : descriptor1, prop2 : descriptor2, ...)
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
keys 遍歷可枚舉的屬性,只包含對(duì)象本身可枚舉屬性,不包含原型鏈可枚舉屬性
let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};
Object.keys(arr) // ['0', '1', '2']
Object.keys(obj) // ["foo","baz"]
Object.keys(ArrayLike) // ['0', '1', '2']
values 遍歷可枚舉的屬性值,只包含對(duì)象本身可枚舉屬性值,不包含原型鏈可枚舉屬性值
let arr = ["a", "b", "c"];
let obj = { foo: "bar", baz: 42 };
let ArrayLike = { 0 : "a", 1 : "b", 2 : "c"};
Object.values(arr) // ["a", "b", "c"]
Object.values(obj) // ["bar",42]
Object.values(ArrayLike) // ["a", "b", "c"]
assign Object.assign( target, source, source1 ) 方法用于對(duì)象的合并,將源對(duì)象(source)的所有可枚舉屬性,復(fù)制到目標(biāo)對(duì)象(target)??截惖膶傩允怯邢拗频?,只拷貝源對(duì)象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)
const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
特殊情況:
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]
Object.assign方法實(shí)行的是淺拷貝,而不是深拷貝。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
console.log(obj2.a.b) //2
obj2.a.b = 3
console.log(obj1.a.b) //3
getPrototypeOf 獲取指定對(duì)象的原型(內(nèi)部[[Prototype]]屬性的值)
const prototype1 = {};
const object1 = Object.create(prototype1);
console.log(Object.getPrototypeOf(object1) === prototype1); // true
注意:Object.getPrototypeOf(Object) 不是 Object.prototype
Object.getPrototypeOf( Object ) === Function.prototype; // true
setPrototypeOf 設(shè)置一個(gè)指定的對(duì)象的原型
const obj = {a: 1}, proto = {b:2}
Object.setPrototypeOf(obj, proto)
obj.__proto__ === proto //true
getOwnPropertyNames 與keys相似,但包含遍歷包含不可枚舉屬性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false
}
});
my_obj.foo = 1;
Object.getOwnPropertyNames(my_obj).sort() // ["foo", "getFoo"]
getOwnPropertyDescriptor 獲取該屬性的描述對(duì)象
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
// { value: 123, writable: true, enumerable: true, configurable: true }
getOwnPropertyDescriptors 返回指定對(duì)象所有自身屬性(非繼承屬性)的描述對(duì)象
Object.getOwnPropertyDescriptors 方法,返回指定對(duì)象所有自身屬性(非繼承屬性)的描述對(duì)象。
const obj = {
foo: 123,
get bar() { return 'abc' }
};
console.dir(Object.getOwnPropertyDescriptors(obj))
// { foo:{ value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:{ get: [Function: bar],
// set: undefined,
// enumerable: true,
// configurable: true }
// }
使用場(chǎng)景:
Object.assign() 方法只能拷貝源對(duì)象的可枚舉的自身屬性,同時(shí)拷貝時(shí)無(wú)法拷貝屬性的特性,而且訪問(wèn)器屬性會(huì)被轉(zhuǎn)換成數(shù)據(jù)屬性,也無(wú)法拷貝源對(duì)象的原型
Object.create() 方法可以實(shí)現(xiàn)上面說(shuō)的這些,配合getPrototypeOf,以及getOwnPropertyDescriptors實(shí)現(xiàn)全面淺拷貝
Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
);
entries 分割對(duì)象
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
// array like object
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
// string
Object.entries('abc') // [['0', 'a'], ['1', 'b'], ['2', 'c']]
Object.entries(100) // []
is 它用來(lái)比較兩個(gè)值是否嚴(yán)格相等,與嚴(yán)格比較運(yùn)算符(===)的行為基本一致
Object.is('foo', 'foo') // true
Object.is({}, {}) // false
不同于 === 之處
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
preventExtensions 讓一個(gè)對(duì)象變的不可擴(kuò)展,也就是永遠(yuǎn)不能再添加新的屬性&isExtensible 判斷一個(gè)對(duì)象是否可擴(kuò)展
let empty = {}
Object.isExtensible(empty) //true
empty.a = 1 //添加成功
//將對(duì)象變?yōu)椴豢赏卣?Object.preventExtensions(empty)
Object.isExtensible(empty) //false
empty.b = 2 //靜默失敗,不拋出錯(cuò)誤
empty.a = 5 //修改a屬性值為5 修改成功
總結(jié):
1.preventExtensions 可以讓這個(gè)對(duì)象變的不可擴(kuò)展,也就是不能再有新的屬性。
2.需要注意的是不可擴(kuò)展的對(duì)象的屬性通常仍然可以被刪除。
3.嘗試給一個(gè)不可擴(kuò)展對(duì)象添加新屬性的操作將會(huì)失敗,不過(guò)可能是靜默失敗,也可能會(huì)拋出 TypeError 異常(嚴(yán)格模式)。
4.Object.preventExtensions 只能阻止一個(gè)對(duì)象不能再添加新的自身屬性,仍然可以為該對(duì)象的原型添加屬性。
seal將一個(gè)對(duì)象密封 isSealed 判斷一個(gè)對(duì)象是否為密封的
密封對(duì)象是指那些不能添加新的屬性,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫(xiě)性,但可能可以修改已有屬性的值的對(duì)象。
1. 先講seal 方法:
var o2 = {b: 1}
o2.d = 2 //添加成功
var obj2 = Object.seal(o2);
obj2 === o2 //true 方法返回原對(duì)象,棧指針指向同一塊內(nèi)存
Object.isSealed(o2) // true
o2.b = 111 //修改b屬性值成功
o2.f = 222 //靜默失敗,屬性f沒(méi)有成功添加
delete o2.b //靜默失敗,屬性b沒(méi)有成功刪除
2. 講isSealed 方法:
let o = {};
Object.isSealed(o) //false
// 之后通過(guò)Object.preventExtensions方法將空對(duì)象設(shè)置為不可擴(kuò)展。
Object.preventExtensions(o);
Object.isSealed(o) // true
但是如果為非空對(duì)象呢?
let o2 = {a: 1}
Object.preventExtensions(o2);
Object.isSealed(o2) // false
因?yàn)閷傩?a 是可配置的(configurable為true),所以不是密封的對(duì)象,修改方法如下:
let o2 = {a: 1}
Object.preventExtensions(o2);
Object.defineProperty(o2, "a", { configurable: false });
Object.isSealed(o2) //true
總結(jié): 1.密封一個(gè)對(duì)象會(huì)讓這個(gè)對(duì)象變的不能添加新屬性,且所有已有屬性會(huì)變的不可配置。
2.屬性不可配置的效果就是屬性變的不可刪除,以及一個(gè)數(shù)據(jù)屬性不能被重新定義成為訪問(wèn)器屬性,或者反之。
3.但屬性的值仍然可以修改。
4.嘗試刪除一個(gè)密封對(duì)象的屬性或者將某個(gè)密封對(duì)象的屬性從數(shù)據(jù)屬性轉(zhuǎn)換成訪問(wèn)器屬性,結(jié)果會(huì)靜默失敗或拋出TypeError 異常(嚴(yán)格模式)。
freeze 凍結(jié)一個(gè)對(duì)象&isFrozen 判斷一個(gè)對(duì)象是否已經(jīng)被凍結(jié)
凍結(jié)對(duì)象是指那些不能添加新的屬性,不能修改已有屬性的值,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫(xiě)性的對(duì)象。也就是說(shuō),這個(gè)對(duì)象永遠(yuǎn)是不可變的。
1.先講freeze 方法:
let o3 = {a: 1}
o3.b = 2 //添加屬性b成功
Object.freeze(o3)
Object.isFrozen(o3) //true 對(duì)象已被凍結(jié)
o3.a = 2 //修改屬性a值失敗
o3.c = 5 //添加屬性c失敗
delete o3.b //刪除屬性b失敗
2.再講isfrozen 方法:
let o4 = {a: 1}
o4.b = 2 // 添加屬性b成功
Object.priventExtensions(o4)
Object.defineProperties(o4, {
a: {configurable: false, writable: false},
b: {configurable: false, writable: false}
})
Object.isFrozen(o4) //true o4 已經(jīng)被凍結(jié)
總結(jié):
1.凍結(jié)對(duì)象的所有自身屬性都不可能以任何方式被修改。
2.任何嘗試修改該對(duì)象的操作都會(huì)失敗,可能是靜默失敗,也可能會(huì)拋出異常(嚴(yán)格模式中)。
3.數(shù)據(jù)屬性的值不可更改,訪問(wèn)器屬性(有g(shù)etter和setter)也同樣(但由于是函數(shù)調(diào)用,給人的錯(cuò)覺(jué)是還是可以修改這個(gè)屬性)。
4.如果一個(gè)屬性的值是個(gè)對(duì)象,則這個(gè)對(duì)象中的屬性是可以修改的,除非它也是個(gè)凍結(jié)對(duì)象。
淺凍結(jié)與深凍結(jié):
(function () {
obj = {
internal :{}
};
Object.freeze(obj);//淺凍結(jié)
obj.internal.a = "aValue";
console.log(obj.internal.a);//"aValue"
//想讓一個(gè)對(duì)象變得完全凍結(jié),凍結(jié)所有對(duì)象中的對(duì)象,可以使用下面的函數(shù).
function deepFreeze(o){
var prop,propKey;
Object.freeze(o);//首先凍結(jié)第一層對(duì)象
for(propKey in o){
prop = o[propKey];
if(!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)){
continue;
}
deepFreeze(prop);//遞歸
}
}
deepFreeze(obj);
obj.internal.b = "bValue";//靜默失敗
console.log(obj.internal.b);//undefined
})();
hasOwnProperty
方法會(huì)返回一個(gè)布爾值,指示對(duì)象自身屬性中是否具有指定的屬性
let o = {a: 1 }
o.hasOwnProperty('a') //true
o.hasOwnProperty('b') //false 對(duì)象自身沒(méi)有屬性b
o.hasOwnProperty('toString'); //false 不能檢測(cè)對(duì)象原型鏈上的屬性
如何遍歷一個(gè)對(duì)象的所有自身屬性,例子:
var buz = {
fog: 'stack'
};
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
console.log("this is fog (" + name + ") for sure. Value: " + buz[name]);
}
else {
console.log(name); // toString or something else
}
}
isPrototypeOf
isPrototypeOf方法用于測(cè)試一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
propertyIsEnumerable指定的屬性是否可枚舉
obj.propertyIsEnumerable(prop) prop為被測(cè)試的屬性名
1. 一般情況下
var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop'); // 返回 true
a.propertyIsEnumerable(0); // 返回 true
2. 瀏覽器內(nèi)置對(duì)象
var a = ['is enumerable'];
a.propertyIsEnumerable(0); // 返回 true
a.propertyIsEnumerable('length'); // 返回 false
Math.propertyIsEnumerable('random'); // 返回 false
this.propertyIsEnumerable('Math'); // 返回 false
3. 自身屬性和繼承屬性
(原型鏈上propertyIsEnumerable不被考慮)
var fn = function(){
this.prop = '123';
}
fn.prototype = { prototypeProp: true}
var o = new fn()
o.propertyIsEnumerable('prop') // true
o.propertyIsEnumerable('prototypeProp') // false
caller 返回當(dāng)前函數(shù)的調(diào)用者
function test(){
if(test.caller == null){
alert("JavaScript頂層作用域調(diào)用了test()函數(shù)");
}else{
alert( test.caller + "函數(shù)調(diào)用了test()函數(shù)");
}
};
test(); // JavaScript頂層作用域調(diào)用了test()函數(shù)
function callTest(){
test();
}
callTest(); // function callTest(){ test(); }函數(shù)調(diào)用了test()函數(shù)
function callTest2(){
// setTimeout()或setInterval()中定時(shí)執(zhí)行的函數(shù)也屬于頂層作用域調(diào)用
setTimeout(test, 5000); // JavaScript頂層作用域調(diào)用了test()函數(shù)
}
callTest2();
valueOf 需要返回對(duì)象的原始值
備注:js對(duì)象中的valueOf()方法和toString()方法非常類似,但是,當(dāng)需要返回對(duì)象的原始值而非字符串的時(shí)候才調(diào)用它,尤其是轉(zhuǎn)換為數(shù)字的時(shí)候。如果在需要使用原始值的上下文中使用了對(duì)象,JavaScript就會(huì)自動(dòng)調(diào)用valueOf()方法。
const o = {a: 1, valueOf: function(){ return 123123 } }
Number(o) //123123
// 給大家出一個(gè)題
const o2 = {
x: 1,
valueOf: function(){
return this.x++
}
}
if(o2 == 1 && o2 == 2 && o2 == 3){
console.log('down')
console.log(o2.x)
}else{
console.log('faild')
}
// Array:返回?cái)?shù)組對(duì)象本身
var array = ["CodePlayer", true, 12, -5];
array.valueOf() === array; // true
// Date:當(dāng)前時(shí)間距1970年1月1日午夜的毫秒數(shù)
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
date.valueOf() // 1376838719230
// Number:返回?cái)?shù)字值
var num = 15.26540;
num.valueOf() // 15.2654
// 布爾:返回布爾值true或false
var bool = true;
bool.valueOf() === bool // true
// new一個(gè)Boolean對(duì)象
var newBool = new Boolean(true);
// valueOf()返回的是true,兩者的值相等
newBool.valueOf() == newBool // true
// 但是不全等,兩者類型不相等,前者是boolean類型,后者是object類型
newBool.valueOf() === newBool // false
// Function:返回函數(shù)本身
function foo(){
}
foo.valueOf() === foo // true
var foo2 = new Function("x", "y", "return x + y;");
foo2.valueOf() === foo2 // true
// Object:返回對(duì)象本身
var obj = {name: "張三", age: 18};
obj.valueOf() === obj // true
// String:返回字符串值
var str = "http://www.365mini.com";
str.valueOf() === str // true
// new一個(gè)字符串對(duì)象
var str2 = new String("http://www.365mini.com");
// 兩者的值相等,但不全等,因?yàn)轭愋筒煌?,前者為string類型,后者為object類型
str2.valueOf() === str2 // false
getOwnPropertySymbols在給定對(duì)象自身上找到的所有 Symbol 屬性的數(shù)組。
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
var objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols.length); // 2
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]) // Symbol(a)
toString toLocalString
toString 方法不做過(guò)多介紹
區(qū)別:
當(dāng)被轉(zhuǎn)化的值是個(gè)時(shí)間對(duì)象時(shí),toLocaleString會(huì)將轉(zhuǎn)化的結(jié)果以本地表示。
(new Date).toString(); //"Mon Nov 06 2017 13:02:46 GMT+0800 (China Standard Time)"
(new Date).toLocaleString(); //"2017/11/6 下午1:03:12"
另外當(dāng)被轉(zhuǎn)化的值是個(gè)時(shí)間戳?xí)r,toLocaleString會(huì)把時(shí)間戳每三位添加一個(gè)逗號(hào),代碼如下。
(Date.parse(new Date())).toLocaleString() //"1,509,944,637,000"
(Date.parse(new Date())).toString() //"1509944643000"
call apply bind 大家自己回去研究
length
Object.length //1
name
Object.name //"Object"
本文作者原創(chuàng),僅供學(xué)習(xí)交流使用,轉(zhuǎn)載需注明出處。