Object
在JavaScript中,几乎所有的对象都是Object的实例,它们都会从Object.prototype继承属性和方法。(MDN定义)
我们在控制台打印一下Object (注意Object O是大写)
console.dir(Object) // ƒ Object()
typeof Object // function
{} instanceof Object // true
[] instanceof Object // true
()=>{} instanceof Object // true
Object()
Object本身是一个函数,可以当作工具方法使用,将任意值转为对象。这个方法常用于保证某个值一定是对象。如果参数为空(或者为undefined和null),Object()返回一个空对象。
var obj = Object(); // {}
// 等同于
var obj = Object(undefined);
var obj = Object(null);
obj instanceof Object // true
上面代码的含义,是将undefined和null转为对象,结果得到了一个空对象obj。
instanceof运算符用来验证,一个对象是否为指定的构造函数的实例。obj instanceof Object返回true,就表示obj对象是Object的实例。
如果参数是原始类型的值,Object方法将其转为对应的包装对象的实例。包装对象请参考我的这篇文章。
var obj = Object(1); 相当于 var obj = new Number(1)
obj instanceof Object // true
obj instanceof Number // true
var obj = Object('foo'); 相当于 var obj = new String("foo")
obj instanceof Object // true
obj instanceof String // true
var obj = Object(true); 相当于 var obj = new Boolean(true)
obj instanceof Object // true
obj instanceof Boolean // true
上面代码中,Object函数的参数是各种原始类型的值,转换成对象就是原始类型值对应的包装对象。
如果Object方法的参数是一个对象,它总是返回该对象,即不用转换。
var arr = [];
var obj = Object(arr); // 返回原数组
obj === arr // true
var value = {};
var obj = Object(value) // 返回原对象
obj === value // true
var fn = function () {};
var obj = Object(fn); // 返回原函数
obj === fn // true
利用这一点,可以写一个判断变量是否为对象的函数。
function isObject(value) {
return value === Object(value);
}
isObject([]) // true
isObject(true) // false
Object()总结:
- 如果参数为 null 或 undefined或空字符串,将会创建并返回一个空对象
- 如果传进去的是一个基本类型的值,则会构造其包装类型的对象
- 如果传进去的是引用类型的值,仍然会返回这个值,返回的值和传进去的值有相同的引用地址
Object 构造函数
Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面可以使用new命令。 Object构造函数的首要用途,是直接通过它来生成新对象。
var obj = new Object();
注意,通过var obj = new Object()的写法生成新对象,与字面量的写法var obj = {}是等价的。或者说,后者只是前者的一种简便写法。
Object构造函数的用法与工具方法可以说是一模一样。使用时,可以接受一个参数,如果该参数是一个对象,则直接返回这个对象;如果是一个原始类型的值,则返回该值对应的包装对象
以下为MDN上的原话
当以非构造函数形式被调用时,Object 的行为等同于 new Object()。
var o1 = {a: 1};
var o2 = new Object(o1);
o1 === o2 // true
var obj = new Object(123);
obj instanceof Number // true
Object 的静态方法
所谓“静态方法”,是指部署在Object对象自身的方法。(只介绍常用)
Object.keys()
Object.keys方法用来遍历对象的属性。参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名。Object.keys方法只返回可枚举的属性
var obj = {
p1: 123,
p2: 456
};
Object.keys(obj) // ["p1", "p2"]
想得到值 而不是属性名可以用 Object.values() 这个方法
Object.assign()
介绍浅拷贝中已经讲过 Object.freeze() 表示冻结一个对象,一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。
const obj = {
prop: 42
};
Object.freeze(obj);
obj.prop = 33; // Throws an error
console.log(obj.prop); // 42
Object.getPrototypeOf()
获取对象的原型(Prototype)对象。
let obj = {}
Object.getPrototypeOf(obj) === obj.__proto__
Object 的实例方法
除了静态方法,还有不少方法定义在Object.prototype对象。它们称为实例方法,所有Object的实例对象都继承了这些方法。
Object实例对象的方法,这里只介绍下面三个
- Object.prototype.valueOf():返回当前对象对应的值。
- Object.prototype.toString():返回当前对象对应的字符串形式。
- Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
Object.prototype.valueOf()
valueOf方法的作用是返回一个对象的“值”,默认情况下返回对象本身。
var obj = new Object();
obj.valueOf() === obj // true
除了下面的例子,可以认为valueOf,都是返回对象的本身。
new Number(123).valueOf() // 123
new String('abc').valueOf() // "abc"
new Boolean(false).valueOf() // false
注意 new Boolean(false) 是一个包装对象,为true。
valueOf方法的主要用途是,JavaScript 自动类型转换时会默认调用这个方法
var obj = new Object();
1 + obj // "1[object Object]"
上面代码将对象obj与数字1相加,这时 JavaScript 就会默认调用valueOf()方法,求出obj的值再与1相加。所以,如果自定义valueOf方法,就可以得到想要的结果。
var obj = new Object();
obj.valueOf = function () {
return 2;
};
1 + obj // 3
上面代码自定义了obj对象的valueOf方法,于是1 + obj就得到了3。这种方法就相当于用自定义的obj.valueOf,覆盖Object.prototype.valueOf。
Object.prototype.toString()
toString方法的作用是返回一个对象的字符串形式,默认情况下返回类型字符串。
var o1 = new Object();
o1.toString() // "[object Object]"
var o2 = {a:1};
o2.toString() // "[object Object]"
上面代码表示,对于一个对象调用toString方法,会返回字符串[object Object],该字符串说明对象的类型。
字符串[object Object]本身没有太大的用处,但是通过自定义toString方法,可以让对象在自动类型转换时,得到想要的字符串形式。
var obj = new Object();
obj.toString = function () {
return 'hello';
};
obj + ' ' + 'world' // "hello world"
上面代码表示,当对象用于字符串加法时,会自动调用toString方法。由于自定义了toString方法,所以返回字符串hello world。
注意:
数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了Object.prototype.toString方法。
[1, 2, 3].toString() // "1,2,3"
'123'.toString() // "123"
(function () {
return 123;
}).toString()
// "function () {
// return 123;
// }"
(new Date()).toString()
// "Tue May 10 2016 09:11:31 GMT+0800 (CST)"
上面代码中,数组、字符串、函数、Date 对象调用toString方法,并不会返回[object Object],因为它们都自定义了toString方法,覆盖了原始方法。
toString() 的应用:判断数据类型
Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型。
由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。
Object.prototype.toString.call(value)
上面代码表示对value这个值调用Object.prototype.toString方法。
不同数据类型的Object.prototype.toString方法返回值如下。
- 数值:返回[object Number]。
- 字符串:返回[object String]。
- 布尔值:返回[object Boolean]。
- undefined:返回[object Undefined]。
- null:返回[object Null]。
- 数组:返回[object Array]。
- arguments 对象:返回[object Arguments]。
- 函数:返回[object Function]。
- Error 对象:返回[object Error]。
- Date 对象:返回[object Date]。
- RegExp 对象:返回[object RegExp]。
- 其他对象:返回[object Object]。 这就是说,Object.prototype.toString可以看出一个值到底是什么类型。
Object.prototype.hasOwnProperty()
Object.prototype.hasOwnProperty方法接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性。
var obj = {
p: 123
};
obj.hasOwnProperty('p') // true
obj.hasOwnProperty('toString') // false
上面代码中,对象obj自身具有p属性,所以返回true。toString属性是继承的,所以返回false。