统统对象都是 Object 的实例,统统函数都是 Function 的实例,Object 是组织函数,函数是 Function 的实例,Function.prototype 是对象,对象是 Object 的实例,能够说 Object 与 Function 是一对密不可分的兄弟,让我们一同解开 Object 与 Function 的神奇面纱,本章重要相识 Object 相干学问,下章再来看 Function
Function instanceof Object // true
Object instanceof Function // true
Object 组织函数能够建立一个对象包装器
JS 中一切对象都来自 Object, 一切对象从 Object.prototype 继续要领和属性
传入的值为 null 或 undefined 将返回一个 {} 空对象
Object(null) // {}
Object(undefined) // {}
Object() 等同于 new Object()
对象字面量
由 {} 包括零个或多个键值对组成以逗号分开的列表组成
对象字面量是属性名及其关联值的鸠合
必需由 逗号 分开
下面是 ES6(ECMAScript 2015) 中对象的定义体式格局
const a = 1;
var obj = {
a,
get a(){},
set a(){},
['a' + 'b']: 'hello',
say(){},
baz: { b: 2 }
}
反复属性
反复的属性,背面的属性会掩盖前面的属性,在ES5中,反复的属性会抛出语法错误 SyntaxError
对象兼并
Object.assign() 能够兼并两个对象,也能够运用睁开符 … 兼并两个对象,Object.assign() 会触发 setter,而睁开操作符则不会
var a = { a: 1 };
var b = { b: 2 };
var mergedObj = Object.assign({}, a, b)
var mergedObj = { ...a, ...b }
变动对象原型
假如给对象的 _proto_ 赋值为 null, 则会变动对象原型,赋值为别的任何值则不会转变对象原型
Object.getPrototypeOf({__proto__:null}) === null
// true
Object.getPrototypeOf({__proto__:{}}) === null
// false
在对象字面值中,只要一次转变原型的时机,屡次变动会报语法错误
不运用 : 定义 _proto__ 不会变动原型,而是会变成对象的一般属性
var __proto__ = "variable";
var obj1 = { __proto__ };
Object.getPrototypeOf(obj1) === Object.prototype
// true
var obj2 = { __proto__() { return "hello"; } };
obj2.__proto__() === "
与JSON区分
对象字面量 与 JSON(JavaScript Object Notation) 的区分
JSON 只允许 以 "property": value 的情势定义属性,且属性名必需以 " 号括起来,属性定义不允许简写
JSON 中的属性值只允许 字符串、数字、数组、true、false、null或别的JSON对象
JSON 中属性值不允许是函数
JSON.parse() 不会处置惩罚盘算属性名,会抛语法错误
Object.length
返回 Object() 组织函数形参数目,值为 1
Object.prototype
Object.prototype.hasOwnProperty()
搜检对象本身中是不是有某属性(疏忽原型链中的属性)
Object.prototype.isPrototypeOf()
搜检当前原型是不是在指定对象的原型中 (作用等同于 instanceof)
Object.prototype.propertyIsEnumerable()
推断属性是不是可罗列
Object.prototype.toLocaleString()
返回对象的字符串示意(用于派生对象重载)
Array.prototype.toLocaleString([locales[,options]])
Number.prototype.toLocaleString([locales[,options]])
Date.prototype.toLocaleString([locales[,options]])
新的 locales 和 options 参数让运用程序能够指定要举行花样转换的言语,而且定制函数的行动
在旧的完成中,会疏忽 locales 和 options 参数,运用的言语环境和返回的字符串的情势完全取决于完成体式格局。
locales 和 options 差别的浏览器及版本有兼容性问题,所以这个api并没有获得普遍的运用
var prices = ['¥7', 500, 8123, 12];
prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' });
// "¥7,¥500,¥8,123,¥12"
const num = 2333333;
num.toLocaleString('zh', { style: 'decimal' }); //2,333,333
num.toLocaleString('zh', { style: 'percent' }); //233,333,300%
const num = 2333333;
num.toLocaleString('zh', { style: 'currency', currency: 'CNY' }); //¥2,333,333.00
num.toLocaleString('zh', { style: 'currency', currency: 'cny', currencyDisplay: 'code' }); //CNY2,333,333.00
let num = 2333.3;
num.toLocaleString('zh', { minimumIntegerDigits: 5 }); //02,333.3
//假如不想有分开符,能够指定useGrouping为false
num.toLocaleString('zh', { minimumIntegerDigits: 5, useGrouping: false }); //02333.3
num.toLocaleString('zh', { minimumFractionDigits: 2, useGrouping: false }); //2333.30
num = 666.666
num.toLocaleString('zh', { maximumFractionDigits: 2, useGrouping: false }); //666.67
Object.prototype.toString()
返回对象的字符串示意
运用 toString 来搜检对象范例
function isNull(){
Object.prototype.toString.call(obj) === ‘[object Null]’
}
Object.prototype.valueOf()
返回一个示意该对象的字符串
Object.assign()
将可罗列的属性从一个或多个源拷贝到目的对象
然则只能深拷贝非嵌套的对象,嵌套属性为浅拷贝
简朴的深拷贝
JSON.parse(JSON.stringify(Obj)), 瑕玷是会损坏对象的原型链,而且会丧失对象的要领
Object.create(proto, [propsObj])
运用指定的原型建立对象
// ES5完成 (不支持 propsObj)
function extend(proto){
function F(){};
F.prototype = proto;
return new F();
}
// 建立一个原型为null的空对象
var o = Object.create(null)
var o = {}
// 相当于
var o = Object.create(Object.prototype)
// 为所建立的对象增添属性 (假如缺省设置,默以为false)
var o = Object.create(Object.prototype, {
foo: {
writeable: true,
configurable: true,
enumerable: true,
value: 'hello'
}
})
function MyClass (){}
var o = new MyClass()
// 相当于
var o = Object.create(Myclass.prototype)
Object.assign 只会拷贝源对象本身且可罗列的属性,会挪用 源对象的 get 和 目的对象的 set 要领,
假如源对象的属性 get 要领是自定义的,兼并后,将会丧失
兼并时,不会跳过那些值为 null 或 undefined 的源对象
Ojbect.assign 的ES5中的 polyfill
Object.defineProperty(Object, 'assign', {
value: function assign(target, varArgs) {
'use strict';
if (target == null) {
throw new TypeError('Connot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index]
for (var nextKey in nextSource) {
if(Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
},
writeable: true,
configurable: true,
})
Object.defineProperty(obj, prop, descriptor)
定义或修正属性对象
obj: 要定义属性的对象
prop: 属性称号
descriptor: 属性形貌
属性形貌 descriptor 分为两种:数据形貌符 和 存取形貌符
数据形貌符:一个有值的属性,可设置 是不是可罗列、是不是可设置、是不是可赋值 及 value值
存取形貌符:有 getter、setter 函数的属性,也可设置 是不是可设置及是不是可罗列
属性形貌只能是 数据形貌 或 存取形貌 中的一种
数据形貌符 形貌的属性只可能有 configurable、enumerable、writeable、value
存取形貌符 形貌的属性只可能有 get、set、configurable、enumerable 四个设置
假如一个形貌符不具有value,writable,get 和 set 恣意一个关键字,那末它将被以为是一个数据形貌符
// 数据形貌符 形貌的属性
Object.defineProperty({}, 'a', {
// 是不是可罗列 决议了是不是可被 for...in 和 Object.keys() 猎取属性名
enumerabel: true,
// 属性形貌是不是可转变,该属性是不是可删除,当前设置为false时,不能在数据和接见器属性范例之间切换,不可删除,除 writable 以外的形貌不可修正
configurable: true,
// 是不是可赋值
writeable: true,
// 属性值,默以为 undefined
value: 1
})
// 存取形貌符 形貌的属性
var bValue;
Object.defineProperty({}, 'b', {
get: function(){
return value;
},
set: function(newValue){
bValue = newValue
},
enumerable: true,
configurable: true,
})
function Archiver () {
var temp = null;
var history = []
Object.defineProperty(this, 'temp', {
get: function () {
console.log('get')
return temp;
},
set: function (newV) {
temp = newV
history.push({val: temp})
}
})
this.getHistory = function(){ return history; };
}
var arc = new Archiver()
arc.temp
arc.temp = 11
arc.temp = 13
arc.getHistory() // [{ val: 11 }, { val: 13 }]
Object.defineProperties(obj, props)
定义或修正多个属性对象 与 Object.defineProperty 一样
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
});
Object.entries()
返回可罗列属性的键值对数组
// 猎取
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
// 遍历 for...of
const obj = { a: 5, b: 7, c: 9};
for(const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`);
}
// 遍历 forEach
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
// Object 转 Map
new Map(Object.entries(obj))
Object.freeze()
凝结一个对象,被凝结的对象,不可增添、删除、修正其属性,也不可修正属性的形貌设置,返回被凝结的对象
只能凝结对象中的第一层的常量对象,不可凝结庞杂对象
obj1 = {
internal: {}
};
Object.freeze(obj1);
obj1.internal.a = 'aValue';
obj1.internal.a // 'aValue'
自定义一个深凝结函数
function deepFreeze(obj){
const propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(name => {
const prop = obj[name];
if(typeof prop === 'object' && prop !== null) {
deepFreeze(prop)
}
})
return Object.freeze(obj)
}
Object.isFrozen()
返回指定对象是不是是凝结对象
Object.seal()
关闭一个对象,对象属性不可删除,不可增添新属性,不可修正属性形貌设置,但 能够修正属性值
const object1 = {
property1: 42
};
Object.seal(object1);
object1.property1 = 33;
console.log(object1.property1);
// expected output: 33
delete object1.property1; // cannot delete when sealed
console.log(object1.property1);
// expected output: 33
Object.isSealed()
返回指定对象是不是是关闭对象
猎取对象本身可罗列的属性
Object.keys()
与 for…in 差别的是:for…in 还会遍历对象原型链中的属性
运用 for…in 猎取对象本身可罗列的属性
for(key in obj) {
obj.hasOwnProperty(key){
console.log(key)
}
}
Object.values()
返回可罗列的属性数组
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
Object.getOwnPropertyNames()
猎取对象本身的属性 (罗列&不能罗列)
猎取对象本身不可罗列的属性?
var allProps = Object.getOwnPropertyNames(obj)
var enumProps = Object.keys(obj)
var noenumProps = allProps.filter(v => enumProps.indexOf(v) === -1)
Object.getOwnPropertySymbols()
返回对象本身一切 Symbol 属性数组
对象本身属性 包括了两种范例,一种是 字符串属性,一种是 Symbol 数据属性,
字符串属性名可由 Object.getOwnPropertyNames() 来猎取
Symbol 属性名可由 Ojbect.getOwnPropertySymbols() 来猎取
默许对象是不含有 Symbol 属性的,除非手动增添了 Symbol 属性
Object.getOwnPropertyDescriptor()
返回 对象本身属性的 形貌设置信息
Object.getOwnPropertyDescriptors()
返回 对象本身一切属性的 形貌设置信息
属性形貌分为两种:存取形貌 与 数据形貌
var o = { get foo() { return 17; } };
var d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
var o = { bar: 42 };
var d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
// configurable: true,
// enumerable: true,
// value: 42,
// writable: true
// }
Object.assign() 没法拷贝源对象属性的特征,且属性形貌会被转为数据形貌,也没法拷贝源对象的原型
运用 Object.create() 能够完全的浅拷贝一个对象
Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj))
Object.getPrototypeOf()
返回指定对象的原型
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
Object.setPrototypeOf()
设置指定对象的原型
这个要领是ES6中的要领,用于替代ES5中 Object.prototype.__proto__ = newProto 的体式格局修正原型
修正原型关于浏览器是一个耗机能的要领,应避免除修正原型,运用 Object.create() 去建立新的对象
Object.is()
同值相称比较 比较两个值是不是相称
与笼统相称 == 区分:
同值相称不会去隐式转换数据范例
与严厉相称 === 区分:
同值相告关于 -0与+0 返回 false, 而严厉相称返回 true
关于 NaN 与 NaN,同值相称返回 true, 严厉相称返回 false
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
0 === -0 //true
+0 === -0 //true
NaN === NaN //false
Object.isExtensible()
推断指定对象是不是能够扩大 (是不是能够增添属性及原型)返回 Boolean
var empty = {};
Object.isExtensible(empty); // === true
Object.preventExtensions()
制止对象扩大 已有的属机能够修正、删除,但不能再增添新的属性