使用Object.getOwnPropertyNames(Object)可以得到
["length", "name", "prototype", "assign", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "getOwnPropertyNames", "getOwnPropertySymbols", "is", "preventExtensions", "seal", "create", "defineProperties", "defineProperty", "freeze", "getPrototypeOf", "setPrototypeOf", "isExtensible", "isFrozen", "isSealed", "keys", "entries", "values"]
这就是对象属性的名称
es6的部分为["is","assign","getOwnPropertyDescriptors","setPrototypeOf","getPrototypeOf","keys","values","entries","fromEntries"]
Object.prototype
表示Object的原型对象
Object.getOwnPropertyNames(Object.prototype)
["constructor", "defineGetter", "defineSetter", "hasOwnProperty", "lookupGetter", "lookupSetter", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "proto", "toLocaleString"]
这是对象原型链上的属性的名称
几乎所有的javascript对象都是Object实例 一个典型的对象继承了Object.prototype的属性(包括方法), 不过这些方法也可以覆盖
Object.create(null)撞见的对象或者通过Object.setPrototypeOf()方法改变原型链 可以创建不具有典型原型链继承的对象
Object.assign(target,sources)
target:目标对象
sources:源对象
用于将所有可美剧属性的值从一个或多个源对象复制到目标对象. 返回目标对象
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = Object.assign({c: 4, d: 5}, object1);
console.log(object2.c, object2.d);
// expected output: 3 5
注意对象属性覆盖问题
针对于深拷贝问题,需要用到其他方法 因为Object.assign()拷贝的是属性值 假如源对象sources的属性值是一个指向对象的引用,它也只拷贝那个引用值。
let obj1 = {a:0,b:{c:0}};
obj2 = Object.assign({},obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj2.b.c = 3
console.log(JSON.stringify(obj1));//{a:1,b:{c:3}}
console.log(JSON.stringify(obj2));//{a:1,b:{c:3}}
// Deep Clone
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
Object.create(proto, [propertiesObject])
proto 新创建对象的原型对象
propertiesObject
创建一个新的对象,使用现有的对象来提供新创建的对象的proto
const person = {
isHuman:false,
printIntroduction:function(){
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = 'Mathew';
me.isHuman = true;
me.printIntroduction();
//My name is Mathew. Am I human? true;
me.__proto__ === person //true
Object.defineProperties(obj,props)
obj 在其上定义或者修改属性的对象
props 要定义其可枚举属性或者修改的属性描述符的对象
可以通过Object.getOwnPropertyDescriptor()来获取每个属性的属性描述符
configurable enumerable value writable get set
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
Object.defineProperty(obj,prop,descriptor)
方法会直接在一个对象定义一个新的属性,或者修改一个对象的现有属性,这个属性是可枚举的,能够在属性枚举期间呈现出来(for...in或者Object.keys())。并返回这个对象 默认情况下,使用这个方法添加的属性值是不可修改的
obj 要在其上定义属性的对象
prop 要定义或者修改的属性的名称
descriptor 将被定义或者修改的属性描述符
Object.defineProperty(obj, "key", {
enumerable: false,
configurable: false,
writable: false,
value: "static"
});
Object.entries(obj)
obj 可以返回其可枚举属性的键值对的对象
返回一个给定对象自身可枚举属性的键值对数组。
排列与使用for...in循环遍历该对象时返回的顺序一直(区别在于for...in循环也枚举原型链中的属性)
const object1 = { foo: 'bar', baz: 42 };
console.log(Object.entries(object1)[1]);
// expected output: Array ["baz", 42]
const object2 = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(object2)[2]);
// expected output: Array ["2", "c"]
const result = Object.entries(object2).sort((a, b) => a - b);
console.log(Object.entries(result)[1]);
// expected output: Array ["1", Array ["1", "b"]]
Object.fromEntries(iterable)
iterable 要迭代的键值对数组
把键值对列表转换成一个对象 相当于Object.entries()的反转函数 但是不知道为什么chrome浏览器不支持这个方法
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }
const object1 = {a:1,b:2,c:3}
const object2 = Object.fromEntries(
Object.entries(object1).map(([key,value]) => {
return [key,value * 2] //这里用到了解构赋值 key 和value 是entries返回的二维数组中的2个值
})
)
console.log(object2);
//{a:2,b:4,c:6}
Object.freeze(obj)
obj要被冻结的对象
方法冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该属性已有属性的可枚举性、可配置性、可写性。该方法返回被冻结的对象
const object1 = {property1:42}
const object2 = Object.freeze(object1)
object2.property1 = 33;
console.log(object2.property1)
//42
Object.isFrozen(obj)
obj被检测的对象
方法判断一个对象是否被冻结 一个对象是冻结的是指它不可扩展 所有属性都是不可配置的 且所有数据属性都是不可写的。
// 一个对象默认是可扩展的,所以它也是非冻结的.
Object.isFrozen({}); // === false
// 一个不可扩展的空对象同时也是一个冻结对象.
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;
// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false
// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为p属性仍然是可以配置的(而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false
// ...如果删除了这个属性,则它会成为一个冻结对象.
delete oneProp.p;
Object.isFrozen(oneProp) //=== true
// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的.
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable) //=== false
// 把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable) //=== true
// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的.
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable) //=== false
// 把这个属性改为不可写,会让这个对象成为冻结对象.
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable) //=== true
// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的.
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) //=== false
// ...但把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) //=== true
// 使用Object.freeze是冻结一个对象最方便的方法.
var frozen = { 1: 81 };
Object.isFrozen(frozen) //=== false
Object.freeze(frozen);
Object.isFrozen(frozen) //=== true
// 一个冻结对象也是一个密封对象.
Object.isSealed(frozen) //=== true
// 当然,更是一个不可扩展的对象.
Object.isExtensible(frozen) //=== false
Object.getOwnPropertyDescriptor(obj,prop)
obj 需要查找的目标的对象
prop目标对象内属性名称(String类型)
方法放回指定对象上一个自由属性对应的属性描述符。(自由属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)。
value writable get set configurable enumerable
var o = {get foo (){return 17}};
var d = Object.getOwnPropertyDescriptor(o,'foo')
//d{
// configurable:true,
// enumerable:true,
// get:/*the getter function*/,
// set:undefined
//}
o = {a:42}
var d = Object.getOwnPropertyDescriptor(o,'a');
//d{
// configurable:true,
// value:42,
// enumerable:true,
// writable:true
//}
Object.getOwnPropertyDescriptors(obj)
obj 任意对象
方法用来获取一个对象的所有自身属性的描述符 如果没有任何自身属性 则返回空对象
o = {a:42}
var d = Object.getOwnPropertyDescriptors(o);
//d{
// configurable:true,
// value:42,
// enumerable:true,
// writable:true
//}
Object.getOwnPropertyNames(obj)
obj 一个对象,其自身的可枚举和不可枚举属性的名称被返回
var arr = [1,3,3];
console.log(Object.getOwnPropertyNames(arr));
// ["0", "1", "2", "length"]
var arr = {0:"a",1:"b"}
console.log(Object.getOwnPropertyNames(arr));
// ["0", "1"]
// 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + " -> " + obj[val]);
});
// 输出
// 0 -> a
// 1 -> b
// 2 -> c
//不可枚举属性依然还是会显示出来
var obj = Object.create({},{
getFoo:{
value:function(){return this.foo},
enumerable:false
}
});
obj.foo = 1;
console.log(Object.getOwnPropertyNames(obj));
// ["getFoo", "foo"]
console.log(Object.getOwnPropertyNames(obj).sort());
// ["foo", "getFoo"]
//如果只想要可枚举的属性可以通过Object.keys()或者for...in来解决 for...in 需要用到Object.hasOwnProperty()方法过滤
//如果只想要不可枚举的属性 可以通过Array.prototype.filter()和Object.keys()来做筛选去掉可枚举的 剩余的就是不可枚举的属性
Object.getOwnPropertySymbols(obj)
obj要返回Symbol属性的对象
方法返回一个给定对象自身的所有Symbol属性的数组
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)
Object.getPrototypeOf(object)
object 要返回其原型的对象
方法返回指定对象的原型
如果给定对象的原型没有继承属性 则返回null 比方说 空对象{}的proto
JavaScript中的 Object 是构造函数(创建对象的包装器)。
一般用法是:
var obj = new Object();
所以:
Object.getPrototypeOf( Object ); // ƒ () { [native code] }
Object.getPrototypeOf( Function ); // ƒ () { [native code] }
Object.getPrototypeOf( Object ) === Function.prototype; // true
Object.getPrototypeOf( Object )是把Object这一构造函数看作对象,
返回的当然是函数对象的原型,也就是 Function.prototype。
正确的方法是,Object.prototype是构造出来的对象的原型。
var obj = new Object();
Object.prototype === Object.getPrototypeOf( obj ); // true
Object.prototype === Object.getPrototypeOf( {} ); // true
Object.setPrototypeOf(obj,prototype)
obj 要设置其原型的对象
prototype 该对象的新原型(一个对象或者null)
方法设置一个指定的对象的原型 到另一个对象或者null
//如果对象的[[prototype]]被修改成不可扩展,就会抛出TypeError异常。如果prototype参数不是一个对象或者null(例如,数字,字符串,boolean,或者undefined),则什么都不做。否则,该方法将obj的[[prototype]]修改为新的值。
//Object.setPrototypeOf()是es6的方法。相对于Object.prototype.__proto__,它被认为是修改对象原型更合适的方法。
var dict = Object.setPrototypeOf({},null);
Object.is(value1,value2)
value1 需要比较的第一个值
value2 需要比较的第二个值
方法判断两个值是否是相同的值 不同于== 和===
这个相同指的是完全相同
- 两个值都是
undefined
- 两个值都是
null
- 两个值都是
true
或者都是false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零
+0
- 都是负零
-0
- 都是
NaN
- 都是除零和
NaN
外的其它同一个数字
- 都是正零
===
运算符运算符会把-0和+0 认为相等 并且Number.NaN 不等于NaN
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
Object.preventExtensions(obj)
obj将要变成不可扩展的对象
方法让一个对象变的不可扩展,也就是永远不能在添加新的属性
返回值为已经不可扩展的对象
//如果一个对象可以添加新的属性,则这个对象是可扩展的。一般来说不可扩展对象的属性可能仍然可被删除。
// Object.preventExtensions将原对象变的不可扩展,并且返回原对象.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2; // true
// 字面量方式定义的对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty) //=== true
// ...但可以改变.
Object.preventExtensions(empty);
Object.isExtensible(empty) //=== false
// 使用Object.defineProperty方法为一个不可扩展的对象添加新属性会抛出异常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出TypeError异常
// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出TypeError异常.
function fail()
{
"use strict";
nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
// 一个不可扩展对象的原型是不可更改的,__proto__是个非标准魔法属性,可以更改一个对象的原型.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // 抛出TypeError异常
Object.isExtensible(obj)
obj需要检测的对象
方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)
// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // === true
// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false
// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false
// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false
seal(obj)
obj将要被密封的对象
返回值:被密封的对象
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。
//通常一个对象是可扩展的(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变得不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义为访问器属性,或者反之,但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError
//不会影响从原型链上继承的属性。但__proto__ 属性的值也会不能修改
//返回被密封对象的引用
var obj = {
prop:function(){},
foo:'bar'
};
// New properties may be added, existing properties
// may be changed or removed.
obj.foo = 'baz';
obj.lumy = 'woof';
delete obj.prop;
var o = Object.seal(obj);
o === obj;//true
Object.isSealed(obj);//true
obj.foo = 'quux';//still work
//but you can not convert data properties to accessors
Object.defineProperty(obj,'foo',{
get:function(){return 'g';}
});//throws a TypeError
obj.quaxxor = 'the friendly duck';
delete obj.foo //silently does not add property
// ...and in strict mode such attempts
// will throw TypeErrors.
function fail() {
'use strict';
delete obj.foo; // throws a TypeError
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// Attempted additions through
// Object.defineProperty will also throw.
Object.defineProperty(obj, 'ohai', {
value: 17
}); // throws a TypeError
Object.defineProperty(obj, 'foo', {
value: 'eit'
}); // changes existing property value
Object.isSealed(obj)
obj 要被检查的对象
方法判断一个对象是否被密封 返回一个Boolean
//新建的对象默认不是密封的
var empty = {};
Objext.isSealed(empty) //=== false
// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true
// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的.
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false
// 如果把这个属性变的不可配置,则这个对象也就成了密封对象.
Object.defineProperty(hasProp, "fee", { configurable: false });
Object.isSealed(hasProp); // === true
// 最简单的方法来生成一个密封对象,当然是使用Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true
// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed); // === false
// 一个密封对象也可以是一个冻结对象,但不是必须的.
Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 属性"p"可写
var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置
Object.keys(obj)
obj 要返回其枚举自身属性的对象
返回值为一个表示给定对象的所有可枚举属性的字符串数组 排列顺序于for...in 循环遍历该对象时返回的顺序一致
// simple array
var arr = ['a','b','c'];
console.log(Object.keys(arr)); //console ['0','1','2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']
Object.hasOwnProperty(prop)
prop要检测的属性 字符串 名称或者Symbol
返回值 用来判断某个对象是否含有指定的属性的Boolean
var o = new Object();
o.prop = 'exists';
function changeO(){
o.newprop = o.prop;
delete o.prop;
}
o.hasOwnProperty('prop');//true
changeO();
o.hasOwnProperty('prop');//false
//自身属性于继承属性
o = new Object();
o.prop = 'exists';
o.hasOwnProperty('prop');//true
o.hasOwnProperty('toString');//false
o.hasOwnProperty('hasOwnProperty');//false
Object.isPrototypeOf(object)
object在该对象的原型链上搜寻
返回值:Boolean 表示调用对象是否在另一个对象的原型链上
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
//也可以用instanceOf 来操作测试构造函数的prototype属性是否出现在对象的原型链中的任何位置
propertyIsEnumerable()
obj.propertyIsEnumerable(prop);
返回值:返回一个Boolean 表示指定的属性是否可枚举
var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop');//true
a.propertyIsEnumerable(0);//true
//用户自定义对象和引擎内置对象
// 下面的例子演示了用户自定义对象和引擎内置对象上属性可枚举的区别
var a = ['is enumerable'];
a.propertyIsEnumerable(0);//true
a.propertyIsEnumerable('length');//false
toLocaleString()
obj.toLocaleString()
返回值:表示对象的字符串 返回调用toString()的结果
方法返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的而重载使用。
Object.toString()
object.toString()
返回值:表示该对象的字符串
每个对象都有一个toString()方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下 toString()方法被每个Object对象继承。如果次方法在定义对象中未被覆盖,同String()返回‘[object type]’,其中type是对象的类型。
var o = new Object()
o.toString();//[object Object]
valueOf()
object.valueOf()
返回值:该对象的原始值
javascript 调用valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,javascript会自动调用它
默认情况下 valueOf方法由Object后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。
javascript许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。
Object.values(obj)
obj被返回可枚举属性值的对象
返回值:一个包含对象自身的所有可枚举属性的数组。
方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同(区别在于for-in循环枚举原型链中的属性)。
var obj = {foo:'bar',baz:42};
console.log(Object.values(obj));//['bar',42]
var obj = {0:‘a’,1:'b',2:'c'};
console.log(Object.values(obj));//['a','b','c']
var an_obj = {100:'a',2:'b',7:'c'};
console.log(Object.values(an_obj));//['b','c','a']
var my_obj = Object.create({},getFoo:{value:function(){return this.foo;}});
my_obj.foo = 'bar';
console.log(Object.values(my_obj));//['bar']
console.log(Object.values('foo'));//['f','o','o']