你不知道的javascript
[]==false true
[]=='' true
''==false true
[]==Array() false
[]===false false
''===false false
null==undefined true
null==false false
undefined==false false
null==true false
null==0 false
undefined==0 false
undefined==‘’ false
null=='' false
Object
Object.getOwnPropertyDescriptor(obj, prop)
检索对象自有属性,存在则返回{属性描述符对象},否则返回undefined
Object.getOwnPropertyDescriptors(obj)
返回对象所有{自身属性的描述符},没有则返回空对象
Object.getPrototypeOf(obj)
返回指定对象的原型对象
Object.getOwnPropertyNames()
返回对象的所有自身属性的属性名(包括不可枚举属性)组成的数组
Object.getOwnPropertySymbols()
返回包含了指定对象自身的(非继承的)所有 symbol 属性键的数组
Object.keys()
返回对象所有可枚举属性名 组成的数组 [name,age]
Object.entries()
返回对象所有可枚举属性的键值对 组成的数组 [[name, “yiqian”],[age, 30]]
Object.values()
返回对象所有可枚举属性的值 [“yiqian”, 30]
for-in 循环
枚举对象自身包括其原型链上的属性
Object.is(a,b)
比较两个值是否是相同的值(不做隐式的类型转换 )
但:Object.is(true,!0) === true 为什么? !0为表达式,会先求值得出true
另:判断两个NaN相等只能使用 Object.is(NaN,NaN)
特例: Object.is(NaN, 0/0) === true
一些概念:
对象与对象属性的描述对象
对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为
描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性。
ES5有三个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性
Object.keys():返回对象自身的所有可枚举的属性的键名
JSON.stringify():只串行化对象自身的可枚举的属性
ES6新增了一个操作Object.assign(),会忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
这四个操作之中,只有for...in会返回继承的属性。实际上,引入enumerable的最初目的,就是让某些属性可以规避掉for...in操作。比如,对象原型的toString方法,以及数组的length属性,就通过这种手段,不会被for...in遍历到。
方法的name属性
const person = { sayName() {console.log('hello!') } };
person.sayName.name === "sayName"
如果对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不是在该方法上面,而是该方法的属性的描述对象的get和set属性上面
const obj = { get foo() {}, set foo(x) {} };
obj.foo.name // TypeError: Cannot read property 'name' of undefined
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
descriptor.get.name // "get foo"
descriptor.set.name // "set foo"
有两种特殊情况:bind方法创造的函数,name属性返回bound加上原函数的名字;Function构造函数创造的函数,name属性返回anonymous。
(new Function()).name // "anonymous"
var doSomething = function() {
// ...
};
doSomething.bind().name // "bound doSomething"
如果对象的方法是一个 Symbol 值,那么name属性返回的是这个 Symbol 值的描述。
const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
key1 {},
key2 {},
};
obj[key1].name // "[description]"
obj[key2].name // ""
上面代码中,key1对应的 Symbol 值有描述,key2没有。
Object.isExtensible(empty)
检测对象是否可扩展
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 // 冻结对象也是不可扩展.
Object.isSealed(empty) 检测对象是否被密封(sealed)
Object.isFrozen(obj) 检测对象是否被冻结(frozen)
也就是说不论是空对象还是非空对象,默认都是非密封非冻结的
//空对象可扩展,非密封非冻结
Object.isSealed({})=== false
Object.isFrozen({}) === false
// 不可扩展的空对象,是密封的,也是冻结的
let empty={};
Object.preventExtensions(empty);
Object.isSealed(empty) === true
Object.isFrozen(empty) === true
// 非空对象变的不可扩展,非密封的(因为密封对象的所有自身属性必须是不可配置的)
var hasProp = { fee: "fie foe fum" , p:42};
Object.preventExtensions(hasProp);
Object.isSealed(hasProp) === false
// 非空对象变的不可扩展,并不一定冻结的,(因为p属性仍然是可以配置的,而且可写的)
Object.isFrozen(hasProp) === false
// 如果删除p属性,则它会成为一个冻结对象.
delete hasProp.p;
Object.isFrozen(hasProp) === true
// 不可扩展对象,如果拥有一个(不可写但可配置)的属性, 非冻结的.非密封的
Object.defineProperty(hasProp, "fee”, { writable: false }); // 变得不可写
Object.isFrozen(hasProp) === false
// 不可扩展的对象,拥有一个(不可配置但可写)的属性, 非冻结的,密封对象
Object.defineProperty(hasProp, “fee”, { configurable: false,writable: true });
Object.isFrozen(hasProp) === false
// 把这个属性改为不可配置(不可写不可配置)冻结对象,密封对象.
Object.defineProperty(hasProp, "e", { configurable: false, writable: false }); // 变得不可配置
Object.isFrozen(hasProp) === true
Object.isSealed(hasProp) === true
// 一个不可扩展的对象,只拥有一个访问器属性,非冻结的.
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) === false
// 把这个属性改为不可配置, 冻结对象.
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) === true
// 生成冻结对象
var frozen = { 1: 81 };
Object.freeze(frozen)
// 一个冻结对象也是一个密封对象.
Object.isSealed(frozen) === true
// 更是一个不可扩展的对象.
Object.isExtensible(frozen) === false
//生成密封对象
var sealed = {};
Object.seal(sealed)
// 一个密封对象同时也是不可扩展的.
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 ,访问器属性不考虑可写不可写,只考虑是否可配置