该博客用js的unitTest验证。
Table of Contents
constructor 属性
Object.assign()
Object.create()
Object.defineProperties()
Object.defineProperty()
Object.entries()
Object.freeze()
Object.fromEntries()
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.getPrototypeOf()
Object.is()
Object.isExtensible()
Object.isFrozen()
Object.isSealed()
Object.keys()
Object.preventExtensions()
hasOwnProperty()
isPrototypeOf()
propertyIsEnumerable()
toLocaleString()
toString()
valueOf()
Object.seal()
Object.setPrototypeOf()
Object.values()
不可扩展对象、密封对象、冻结对象的总结
constructor
属性返回创建实例对象的 Object
构造函数的引用。
describe('Object.prototype.constructor',function(){
it('All objects inherit constructor property from its prototype.',function(){
let object1={};
object1.constructor.should.equal(Object);
let object2=new Object();
object2.constructor.should.equal(Object);
let array1=[];
array1.constructor.should.equal(Array);
let array2=new Array();
array2.constructor.should.equal(Array);
});
});
- 所有对象都会从它的原型上继承一个
constructor
属性
将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
describe('Object.assign()', function () {
it('source object is copied to target object.', function () {
let source = { a: 1, b: 2 };
let target = { c: 3, d: 4 };
let result = Object.assign(source, target);
console.log(result); //{ a: 1, b: 2, c: 3, d: 4 }
result.should.not.equal({ a: 1, b: 2, c: 3, d: 4 });
result.should.equal(source);
let target1 = { b: 8888, d: 4 };
let result1 = Object.assign(source, target1);
console.log(result1); //{ a: 1, b: 8888, c: 3, d: 4 }
result1.should.equal(source);
})
it('Inheritance properties and non-enumerated properties cannot be copied.', function () {
let object = Object.create(
{ age: 18 }, //age是个继承属性
{
name: { //name是不可枚举属性
value: "mandy"
},
salary: { //salary是自身可枚举属性
value: "99999",
enumerable: true,
}
});
let result = Object.assign({}, object);
console.log(result); //{ salary: '99999' }
result.should.not.equal(object);
});
it('original type is wrapped as an object.', function () {
let str = "abc";
let boo = true;
let num = 100;
let result =Object.assign({},null,boo,undefined,str,num);
console.log(result); //{ '0': 'a', '1': 'b', '2': 'c' }
});
})
- 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。
- 后面的源对象的属性将类似地覆盖前面的源对象的属性。
- 该方法只会拷贝源对象自身的并且可枚举的属性到目标对象.
- 源对象会改变。
- 继承属性和不可枚举属性是不能拷贝的。
- 原始类型会被包装为对象
原始类型会被包装,null 和 undefined 会被忽略。
注意,只有字符串的包装对象才可能有自身可枚举属性。
Object.create()
创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
describe('Object.create()', function () {
it('new object.', function () {
const person = {
isGirl: false,
info: function () {
return 'My name is ' + this.name + ' ,am I a girl : ' + this.isGirl;
}
}
const result = Object.create(person);
result.name = "mandy";
result.isGirl = true;
console.log(result); //{ name: 'mandy', isGirl: true }
result.info().should.equal("My name is mandy ,am I a girl : true");
});
})
- 返回一个新对象,带着指定的原型对象和属性。
Object.defineProperties()
在一个对象上定义新的属性或修改现有属性,并返回该对象。
describe('Object.defineProperties', function () {
it('Define new property or modify existing property.', function () {
let object = {};
Object.defineProperties(object, {
name: {
value: "mandy",
writable: true,
enumerable: true,
},
age:{
value:18,
writable:true,
}
})
console.log(object); //{ name: 'mandy' }
object.should.not.null();
})
})
props
要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅
Object.defineProperty()
)。描述符具有以下键:
configurable
true
当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。
默认为false
enumerable
true
当且仅当在枚举相应对象上的属性时该属性显现。
默认为false
value
与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。
默认为undefined
.
writable
true
当且仅当与该属性相关联的值可以用assignment operator改变时。
默认为false
get
作为该属性的 getter 函数,如果没有 getter 则为
undefined
。函数返回值将被用作属性的值。
默认为undefined
set
作为属性的 setter 函数,如果没有 setter 则为
undefined
。函数将仅接受参数赋值给该属性的新值。
默认为undefined
Object.defineProperty()
直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
describe('Object.defineProperty()', function () {
it('Define new property or modify an existing property.', function () {
let object = {};
Object.defineProperty(object, "name", {
value: "mandy",
enumerable: true
});
console.log(object); //{ name: 'mandy' }
object.name.should.equal("mandy");
})
})
备注:应当直接在
Object
构造器对象上调用此方法,而不是在任意一个Object
类型的实例上调用。
Object.entries()
返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in
循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
describe('Object.entries()', function () {
let object = { name: "mandy", age: 18 };
it('Traverse the object.', function () {
for(let [key,value] of Object.entries(object)){
console.log(key+" : "+value);
//name : mandy
//age : 18
}
})
it('array like object',function(){
let result=Object.entries(object);
console.log(result); //[ [ 'name', 'mandy' ], [ 'age', 18 ] ]
Array.isArray(result).should.equal(true)
})
})
Object.freeze()
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。
describe('Object.freeze()', function () {
it('Frozen objects are immutable.', function () {
let object = {
name: "mandy",
age: 18
}
Object.freeze(object);
object.name = "chen";
delete object.age;
object.name.should.equal("mandy");
should(object).has.properties("name", "age");
})
})
Object.fromEntries()
方法把键值对列表转换为一个对象。
describe('Object.fromEntries()', function () {
it('key-value pair to an object.', function () {
let map = new Map([["name", "mandy"], ["age", 18]]);
let result = Object.fromEntries(map);
console.log(result); //{ name: 'mandy', age: 18 }
result.constructor.should.equal(Object);
})
})
Object.fromEntries()
执行与Object.entries
互逆的操作。
Object.getOwnPropertyDescriptor()
返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
describe('Object.getOwnPropertyDescriptor()', function () {
it('The property descriptor for the own property.', function () {
let object = {
name: {
value: "mandy",
enumerable: true,
writable: true
}
};
let des = Object.getOwnPropertyDescriptor(object, "name");
console.log(des);
des.writable.should.equal(true);
des.value.value.should.equal("mandy");
des.enumerable.should.equal(true);
})
})
Object.getOwnPropertyDescriptors()
用来获取一个对象的所有自身属性的描述符。
describe('Object.getOwnPropertyDescriptors', function () {
it('Gets all descriptors for the object.', function () {
let object = { name: "mandy" };
let result = Object.getOwnPropertyDescriptors(object);
console.log(result);
// {
// name: {
// value: 'mandy',
// writable: true,
// enumerable: true,
// configurable: true
// }
// }
})
})
Object.getOwnPropertyNames()
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
describe('Object.getOwnPropertyNames()', function () {
it('The property names of its own properties make up an array.', function () {
let arr = ["a", "b", "c"];
let object = { name: "mandy", age: 18 }
let result1 = Object.getOwnPropertyNames(arr);
let result2 = Object.getOwnPropertyNames(object);
console.log(result1); //[ '0', '1', '2', 'length' ]
console.log(result2); //[ 'name', 'age' ]
})
})
Object.getOwnPropertySymbols()
返回一个给定对象自身的所有 Symbol 属性的数组。
describe(' Object.getOwnPropertySymbols()', function () {
it('An array of all Symbol properties of the object itself.', function () {
let object = {};
let a = Symbol("a");
let b = Symbol.for("b");
object[a] = "localSymbol";
object[b] = "globalSymbol";
let objectSymbols = Object.getOwnPropertySymbols(object);
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]) // Symbol(a)
objectSymbols.length.should.equal(2);
})
})
Object.getPrototypeOf()
返回指定对象的原型(内部[[Prototype]]
属性的值)。
describe('Object.getPrototypeOf()', function () {
it('return object of the prototype.', function () {
let object = {};
let result = Object.create(object);
console.log(result);
Object.getPrototypeOf(result).should.equal(object);
})
})
- 返回给定对象的原型。如果没有继承属性,则返回
null
。
Object.is()
判断两个值是否为同一个值。
describe('Object.is()', function () {
it('Determines whether two values are the same.', function () {
let object1 = { name: "mandy" };
let object2 = { name: "mandy" };
Object.is("mandy", "mandy").should.equal(true);
Object.is(object1, object2).should.equal(false);
})
})
与
==
运算不同。==
运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将"" == false
判断为true
), 而Object.is
不会强制转换两边的值。与
===
运算也不相同。===
运算符 (也包括==
运算符) 将数字-0
和+0
视为相等 ,而将Number.NaN
与NaN
视为不相等.如果满足以下条件则两个值相等:
都是
undefined
都是
null
都是
true
或false
都是相同长度的字符串且相同字符按相同顺序排列
都是相同对象(意味着每个对象有同一个引用)
都是数字且
都是
+0
都是
-0
都是
NaN
或都是非零而且非
NaN
且为同一个值
Object.isExtensible()
判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
describe('Object.isExtensible() ', function () {
it('Determines whether the object is scalable.', function () {
let object = {};
Object.isExtensible(object).should.equal(true);
Object.preventExtensions(object);
Object.isExtensible(object).should.equal(false);
let sealed = Object.isSealed({});
Object.isExtensible(sealed).should.equal(false);
let freeze = Object.freeze({});
Object.isExtensible(freeze).should.equal(false);
})
})
- 新对象默认是可扩展的.
- 用Object.preventExtensions(empty)变得不可扩展
- 密封对象是不可扩展的
- 冻结对象不可扩展
Object.isFrozen()
判断一个对象是否被冻结。
describe('Object.isFrozen()', function () {
it('Is Frozen', function () {
//初始的空对象默认是非冻结对象
Object.isFrozen({}).should.equal(false);
//不可扩展的空对象是冻结对象
let preExten = Object.preventExtensions({});
Object.isFrozen(preExten).should.equal(true);
// 一个非空对象默认是非冻结对象
var object = { name: "mandy" };
Object.isFrozen(object).should.equal(false);
// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象
// 因为name属性仍然是可以配置的(而且可写的).
Object.preventExtensions(object);
Object.isFrozen(object).should.equal(false);
// 此时,如果删除了这个属性,则它会成为一个冻结对象.
delete object.name;
Object.isFrozen(object).should.equal(true)
})
})
- 一个对象是冻结的是指它不可
扩展
,所有属性都是不可配置的,且所有数据属性(即没有getter或setter组件的访问器的属性)都是不可写的。
Object.isSealed()
判断一个对象是否被密封。
describe(' Object.isSealed()', function () {
it('Is sealed', function () {
let empty = {};
// 新建的对象默认不是密封的.
Object.isSealed(empty).should.equal(false);
// 如果空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty).should.equal(true);
// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的.
var object1 = { name: "mandy" };
Object.preventExtensions(object1);
Object.isSealed(object1).should.equal(false);
// 如果把这个属性变的不可配置,则这个属性也就成了密封对象.
Object.defineProperty(object1, "name", { configurable: false });
Object.isSealed(object1).should.equal(true);
// 生成密封对象
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed).should.equal(true);
// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed).should.equal(false);
// 一个密封对象也可以是一个冻结对象,但不是必须的.
Object.isFrozen(sealed).should.equal(true);
var object2 = Object.seal({ age: 18 });
Object.isFrozen(object2).should.equal(false);
var object3 = Object.seal({ get name() { return "mandy"; } });
Object.isFrozen(object3).should.equal(true);
})
})
- 密封对象是指那些不可
扩展
的,且所有自身属性都不可配置且因此不可删除(但不一定是不可写)的对象。
Object.keys()
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
describe('Object.keys()', function () {
it('Return properties of the object.', function () {
let object = { name: "mandy", age: 18 }
let result = Object.keys(object);
// let result = Object.getOwnPropertyNames(object);
console.log(result); //[ 'name', 'age' ]
result.should.not.equal([ 'name', 'age' ])
})
})
- 与Object.getOwnPropertyNames()有相似之处,如上代码,Object.keys(object)和Object.getOwnPropertyNames(object)的结果是一样的。
- 但是也有区别:
Object.keys()
返回的是一个表示给定对象的所有可枚举属性的字符串数组。如果你想获取一个对象的所有属性,,甚至包括不可枚举的,请查看
Object.getOwnPropertyNames
Object.preventExtensions()
让一个对象变的不可扩展,也就是永远不能再添加新的属性。
describe('Object.preventExtensions()', function () {
it('Cannot add a new property.', function () {
let object = Object.preventExtensions({});
try {
Object.defineProperty(object, "name", {
value: "mandy"
})
} catch (e) {
console.log(e);
}
})
})
hasOwnProperty()
会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
describe('hasOwnProperty() ', function () {
it('Whether there are specified properties.', function () {
let object = {};
object.hasOwnProperty("name").should.equal(false);
object.name="mandy";
object.hasOwnProperty("name").should.equal(true);
})
})
- 即使属性的值是
null
或undefined
,只要属性存在,hasOwnProperty
依旧会返回true
。
isPrototypeOf()
用于测试一个对象是否存在于另一个对象的原型链上。
describe('isPrototypeOf()', function () {
it('Whether the object is on the prototype chain of another object.', function () {
function Large(){};
function Middle(){};
function Small(){};
Middle.prototype=Object.create(Large.prototype);
Small.prototype=Object.create(Middle.prototype);
let small=new Small();
Small.prototype.isPrototypeOf(small).should.equal(true);
Middle.prototype.isPrototypeOf(small).should.equal(true);
Large.prototype.isPrototypeOf(small).should.equal(true);
})
})
propertyIsEnumerable()
返回一个布尔值,表示指定的属性是否可枚举。
describe('propertyIsEnumerable()', function () {
it('Is Enumerable of property', function () {
let object={};
let array=[];
object.name="mandy";
array[0]="mandy";
object.propertyIsEnumerable("name");
array.propertyIsEnumerable(0);
array.propertyIsEnumerable("length");
})
})
toLocaleString()
返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。
describe('toLocaleString() ', function () {
it('Returns the string of the object.', function () {
let object = { name: 'mandy', age: 18 };
console.log(object.toLocaleString()); //[object Object]
})
})
toString()
返回一个表示该对象的字符串。
describe('toString()', function () {
it('Return the string of the object.', function () {
function Person(name) {
this.name = name;
}
let person = new Person("mandy");
Person.prototype.toString = function PersonToString() {
return `${this.name}`;
}
person.toString().should.equal("mandy");
})
})
valueOf()
返回指定对象的原始值。
describe('valueOf()', function () {
it('Return the original value of the specified object.', function () {
let array=[1,2,3,4];
array.valueOf().should.equal(array);
let num=999;
num.valueOf().should.equal(999)
let fun=new Function("mandy");
console.log(fun);
let object={name:"mandy",age:19};
console.log(object.valueOf()); //{ name: 'mandy', age: 19 }
})
})
Object.seal()
封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
describe('Object.seal()', function () {
it('Prevents new properties from being added and marks all existing properties as non-configurable.',
function () {
let object = {
name: "mandy"
}
Object.seal(object);
object.name = "chen";
object.name.should.equal("chen");
delete object.name;
object.name.should.equal("chen");
})
});
- 通常,一个对象是可扩展的(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出
TypeError
(在严格模式 中最常见的,但不唯一)。- 对比
Object.freeze()
使用
Object.freeze()
冻结的对象中的现有属性值是不可变的。用Object.seal()
密封的对象可以改变其现有属性值。
设置一个指定的对象的原型 ( 即内部[[Prototype]]属性)到另一个对象或 null
。
describe('Object.setPrototypeOf() ', function () {
it('Set prototype of object to another object or null.', function () {
let object = Object.setPrototypeOf({}, null);
console.log(object); //[Object: null prototype] {}
})
})
- 更改对象的
[[Prototype]]
是一个很慢的操作,应该避免使用,
应该使用Object.create()
来创建想要的[[Prototype]]
的新对象。
Object.values()
返回一个给定对象自身的所有可枚举属性值的数组
describe('Object.values()', function () {
it('Returns array of all enumerable property values for object.', function () {
let object = { name: "mandy", age: 18 }
console.log(Object.values(object)); //[ 'mandy', 18 ]
Object.values(object).should.not.equal([ 'mandy', 18 ]);
console.log(Object.values("abc")); //[ 'a', 'b', 'c' ]
Object.values("abc").should.not.equal([ 'a', 'b', 'c' ])
})
})
Object.preventExtensions()
方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
如果一个对象可以添加新的属性,则这个对象是可扩展的。Object.preventExtensions()
将对象标记为不再可扩展,这样它将永远不会具有它被标记为不可扩展时持有的属性之外的属性。注意,一般来说,不可扩展对象的属性可能仍然可被删除。尝试将新属性添加到不可扩展对象将静默失败或抛出TypeError
(最常见的情况是strict mode中,但不排除其他情况)。
Object.preventExtensions()
仅阻止添加自身的属性。但其对象类型的原型依然可以添加新的属性。
该方法使得目标对象的 [[prototype]]
不可变;任何重新赋值 [[prototype]]
操作都会抛出 TypeError
。这种行为只针对内部的 [[prototype]]
属性, 目标对象的其它属性将保持可变。
一旦将对象变为不可扩展的对象,就再也不能使其可扩展。
Object.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
通常,一个对象是可扩展的(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。但属性的值仍然可以修改。尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError
(在严格模式 中最常见的,但不唯一)。
不会影响从原型链上继承的属性。
Object.freeze()
方法可以冻结一个对象。
一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。
被冻结对象自身的所有属性都不可能以任何方式被修改。任何修改尝试都会失败,无论是静默地还是通过抛出TypeError
异常(最常见但不仅限于strict mode)。
数据属性的值不可更改,访问器属性(有getter和setter)也同样(但由于是函数调用,给人的错觉是还是可以修改这个属性)。如果一个属性的值是个对象,则这个对象中的属性是可以修改的,除非它也是个冻结对象。数组作为一种对象,被冻结,其元素不能被修改。没有数组元素可以被添加或移除。
这个方法返回传递的对象,而不是创建一个被冻结的副本。