标准库-Object对象
概要
JS原生提供Object对象
下面是关于该对象原生各种方法的笔记
JS的所有其他对象都继承于Object对象(也即所有其他对象都是Object的实例)
Object对象的原生方法分为Object本身的方法以及Object的实例方法
1 Object对象本身方法
直接定义在Object对象的方法
Object.print = function (o) { console.log(o) };
上面代码中print方法直接定义在Object对象上
2 Object实例方法
实例方法是定义在Object原型对象Object.prototype上的方法
可以被Object实例直接使用
Object.prototype.print = function () {
console.log(this);
};
var obj = new Object();
obj.print() // Object
上面代码中,Object.prototype定义了一个print方法,然后生成一个Object的实例obj
obj直接继承了Object.prototype的属性和方法,可以直接使用obj.print调用print方法
也就是说obj对象的print方法实质上就是调用Object.prototype.print方法
首先我们要知道Object作为函数的用法
而后知道Object对象的原生方法(分为对象自身方法也即静态方法与实例方法两部分)
Object()
Object的本身是一个函数
可以作为工具方法使用,用于将任意值转为对象(常用于保证某个值一定为对象)
如果参数为空(或者为undefined和null),Object()返回一个空对象
instanceof运算符用来验证一个对象是否为指定的构造函数的实例
var obj = Object();
// 等价于
var obj = Object(undefined);
var obj = Object(null);
obj instanceof Object // true
如果参数是原始类型的值,Object方法将其转为对应的包装对象的实例
var obj = Object(1);
obj instanceof Object // true
obj instanceof Number // true
var obj = Object('zane');
obj instanceof Object // true
obj instanceof String // true
var obj = Object(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构造函数
Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面可以使用new命令
Object构造函数的首要用途,是直接通过它来生成新对象
var obj = new Object();
以上写法生成新对象与字面量的写法var obj = {}
是等价的
或者说后者是前者的简写
Object构造函数的用法与工具方法很相似
使用时可以接受一个参数,如果该参数是一个对象,则直接返回这个对象
如果是一个原始类型的值,则返回该值对应的包装对象
var o1 = {a: 1};
var o2 = new Object(o1);
o1 === o2 // true
var obj = new Object(123);
obj instanceof Number // true
虽然用法相似,但是Object(value)与new Object(value)两者的语义是不同的
Object(value)表示将value转成一个对象
new Object(value)则表示新生成一个对象且值是value
Object静态方法
静态方法即是部署在Object对象自身的方法
1 Object.keys(), Object.getOwnPropertyNames()
Object.keys方法和Object.getOwnPropertyNames方法都用来遍历对象的属性
Object.keys方法的参数是一个对象,返回一个数组
该数组的成员都是该对象自身的(而不是继承的)所有属性名
var obj = {
p1: 123,
p2: 456
};
Object.keys(obj) // ["p1", "p2"]
Object.getOwnPropertyNames方法与Object.keys类似,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名
var obj = {
p1: 123,
p2: 678
};
Object.getOwnPropertyNames(obj) // ["p1", "p2"]
对于一般的对象来说,Object.keys()和Object.getOwnPropertyNames()返回的结果是一样的
只有涉及不可枚举属性时,才会有不一样的结果。Object.keys方法只返回可枚举的属性
Object.getOwnPropertyNames方法还可以返回不可枚举的属性名
var a = ['hello', 'zane'];
Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]
上面代码中,数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中
JS没有计算对象属性个数的方法
可以变换此两种方法使用
var obj = {
p1: 123,
p2: 789
};
Object.keys(obj).length // 2
Object.getOwnPropertyNames(obj).length // 2
一般情况下几乎总是使用Object.keys方法,遍历对象的属性
2 Other methods
Object有很多静态方法
- 对象属性模型的相关方法
- Object.getOwnPropertyDescriptor():获取某个属性的描述对象
- Object.defineProperty():通过描述对象来定义某个属性
- Object.defineProperties():通过描述对象定义多个属性
- 控制对象状态的方法
- Object.preventExtensions():防止对象扩展
- Object.isExtensible():判断对象是否可拓展
- Object.seal():禁止对象配置
- Object.isSealed():判断一个对象是否可配置
- Object.freeze():冻结一个对象
- Object.isFrozen():判断一个对象是否被冻结
- 原型链相关方法
- Object.create():该方法可以指定原型对象和属性并返回一个新的对象
- Object.getPrototypeOf():获取对象的Prototype对象
Object实例方法
除了静态方法,还有不少方法定义在Object.prototype对象中,也即实例方法
所有Object的实例对象都继承这些方法
Object实例对象的方法,主要有以下六个
- Object.prototype.valueOf():返回当前对象对应的值
- Object.prototype.toString():返回当前对象对应的字符串形式
- Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式
- Object.prototype.hasOwnProperty():判断某个属性是否是当前对象自身的属性还是继承自原型对象的属性
- Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型
- Object.prototype.propertyIsEnumerable():判断某个属性是否可以枚举
1 Object.prototype.valueOf()
valueOf方法的作用是返回对象的值
默认情况下返回对象本身
var obj = new Object();
obj.valueOf() === obj // 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 6;
};
1 + obj // 7
上面代码自定义的obj对象的valueOf方法覆盖Object.prototype.valueOf
2 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 'zane';
};
obj + ' ' + 'world' // "zane world"
上面代码表示当对象用于字符串加法时,会自动调用toString方法
由于自定义了toString方法,所以返回字符串zane 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 Sep 05 2023 18:42:39 GMT+0800 (中国标准时间)'
上面代码中数组、字符串、函数、Date 对象调用toString方法并不会返回[object Object],因为它们都自定义了toString方法,覆盖原始方法
3 toString() 的应用:判断数据类型
Object.prototype.toString方法返回对象的类型字符串
因此可以用来判断一个值的类型
var obj = {};
obj.toString() // "[object Object]"
上面代码调用空对象的toString方法,结果返回一个字符串object Object,其中第二个Object表示该值的构造函数
是十分有用的判断数据类型的方法
由于实例对象可能会自定义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.call(2) // "[object Number]"
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"
利用这个特性,可以写出一个比typeof运算符更准确的类型判断函数
var type = function (o) {
var s = Object.prototype.toString.call(o);
return s.match(/\[objct (.*?)\]/)[1].toLowerCase();
};
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regexp"
type(new Date()); // "date"
在上面这个type函数的基础上还可以加上专门判断某种类型数据的方法
var type = function (o) {
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
['Null',
'Undefined',
'Object',
'Array',
'String',
'Number',
'Boolean',
'Function',
'RegExp'
].forEach(function (t) {
type['is' + t] = function (o) {
return type(o) === t.toLowerCase();
};
});
type.isObject({}) // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true
4 Object.prototype.toLocaleString()
Object.prototype.toLocaleString方法与toString的返回结果相同
var obj = {};
obj.toString(obj) // "[object Object]"
obj.toLocaleString(obj) // "[object Object]"
这个方法的主要作用是留出一个接口,让各种不同的对象实现自己版本的toLocaleString
用来返回针对某些地域的特定的值
var person = {
toString: function () {
return 'Henry Norman Behthune';
},
toLocaleString: function () {
return '白求恩';
}
};
person.toString() // Henry Norman Bethune
person.toLocaleString() // 白求恩
目前主要有三个对象自定义了toLocaleString方法
- Array.prototype.toLocaleString()
- Number.prototype.toLocaleString()
- Date.prototype.toLocaleString()
举例来说,日期的实例对象的toString和toLocaleString返回值就不一样
而且toLocaleString的返回值跟用户设定的所在地域相关
var date = new Date();
date.toString() // "Tue Jan 01 2018 12:01:33 GMT+0800 (CST)"
date.toLocaleString() // "1/01/2018, 12:01:33 PM"
5 Object.prototype.hasOwnProperty()
接受一个字符串作为参数并返回一个布尔值
用于表示该实例对象自身是否拥有该属性
var obj = {
p: 123
};
obj.hasOwnProperty('p') // true
obj.hasOwnProperty('toString') // false
toString属性是继承的,所以返回false