概述
JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例
Object对象的原生方法分成两类:Object本身的方法与Object的实例方法
1)Object对象本身的方法
所谓“本身的方法”就是直接定义在Object对象的方法
2)Object的实例方法
所谓实例方法就是定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用。
Object本身是一个函数,可以当作工具方法使用,将任意值转为对象
如果参数为空(或者为undefined和null),Object()返回一个空对象
如果参数是原始类型的值,Object方法将其转为对应的包装对象的实例
var obj = Object(1);
obj instanceof Object // true
obj instanceof Number // true
var obj = Object('foo');
obj instanceof Object // true
obj instanceof String // true
var obj = Object(true);
obj instanceof Object // true
obj instanceof Boolean // true
如果Object方法的参数是一个对象,它总是返回该对象,即不用转换
利用这一点,可以写一个判断变量是否为对象的函数。
function isObject(value) {
return value === Object(value);
}
isObject([]) // true
isObject(true) // false
Object 构造函数
Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面可以使用new命令
Object(value)与new Object(value)两者的语义是不同的,Object(value)表示将value转成一个对象,new Object(value)则表示新生成一个对象,它的值是value。
Object 的实例方法 toString() 的应用:判断数据类型
Object.prototype.toString.call(value)
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"
对象(object)是 JavaScript 最重要的数据结构。ES6 对它进行了重大升级
数据结构本身的改变
(1)属性的简洁表示法
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo};
(2)属性名表达式
JavaScript 定义对象的属性,有两种方法。
方法一 直接用标识符作为属性名
obj.foo = true;
方法二 用表达式作为属性名 要将表达式放在方括号之内
obj['a' + 'bc'] = 123;
注意,属性名表达式与简洁表示法,不能同时使用,会报错。
报错:
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };
正确:
const foo = 'bar';
const baz = { [foo]: 'abc'};
(3)方法的 name 属性
函数的name属性,返回函数名。对象方法也是函数,因此也有name属性。
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name // "sayName"
(4)属性的遍历
ES6 一共有 5 种方法可以遍历对象的属性。
1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。
(5)super 关键字
我们知道,this关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super,指向当前对象的原型对象。
注意,super关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
JavaScript 引擎内部,super.foo等同于Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)。
const proto = {
x: 'hello',
foo() {
console.log(this.x);
},
};
const obj = {
x: 'world',
foo() {
super.foo();
}
}
Object.setPrototypeOf(obj, proto);
obj.foo() // "world"
上面代码中,super.foo指向原型对象proto的foo方法,但是绑定的this却还是当前对象obj,因此输出的就是world。
(6)克隆和拷贝
对象的扩展运算符等同于使用Object.assign()方法。
let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);
上面的例子只是拷贝了对象实例的属性,如果想完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法。
写法一
const clone1 = {
__proto__: Object.getPrototypeOf(obj),
...obj
};
写法二
const clone2 = Object.assign(
Object.create(Object.getPrototypeOf(obj)),
obj
);
写法三
const clone3 = Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
上面代码中,写法一的__proto__属性在非浏览器的环境不一定部署,因此推荐使用写法二和写法三。
扩展运算符可以用于合并两个对象。
let ab = { ...a, ...b };
等同于
let ab = Object.assign({}, a, b);
Object对象的新增方法
(1)Object.is()
它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
(2) Object.assign()
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
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}
Object.assign方法实行的是浅拷贝
(3)Object.getOwnPropertyDescriptors()
ES5 的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。
(4)__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括 IE11)都部署了这个属性。
Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法
(5)Object.keys(),Object.values(),Object.entries() Object.fromEntries()
ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
// 例一
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
Object.fromEntries(entries)
// { foo: "bar", baz: 42 }
// 例二
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }
该方法的一个用处是配合URLSearchParams对象,将查询字符串转为对象。
Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }