先回顾下ES5中常用对象方法:
Object的静态方法,所为静态方法是指部署在Object对象自身的方法。
Object . keys
参数是对象,返回一个数组;该数组的成员是该对象自身的(而不是继承的)所有属性名。(可枚举的属性)
eg:
var obj = {name:"lxc",age:25}
Object.keys(obj)//["name","age"]
Object.values
参数是对象,返回一个数组;该数组的成员是该对象自身的(而不是继承的)所有属性值。(可枚举的属性)
var obj = {name:"lxc",age:25}
Object.keys(obj)//["name","age"]
Object.getOwnPropertyNames
——也用来遍历对象的属性,接受一个对象作为参数,返回一个数组,包含了该对象自身的所有的属性名。
eg:
var obj = {name:"lxc",age:25}
Object.getOwnPropertyNames(obj)//["name","age"]
两者区别在于,getOwnPropertyNames方法可返回不可枚举的属性名:
eg:数组的length方法是不可枚举的,所以出现在getOwnPropertyNames中
var arr = ["lv","xc"];
Object.keys(arr);//["0","1"]
Object.getOwnPropertyNames(arr);//["0","1","length"]
由于js中没有提供计算对象属性个数的方法,所以可以用这两个方法来代替:
var obj = {name:"lxc",age:25}
Object.getOwnPropertyNames(obj).length;//2
Object.keys(obj).length;//2
Object的实例方法,它是定义在对象的原型上边的,所有的Object实例方法都继承了这些方法。
Object实例对象的方法主要有以下六个:
Object.prototype.valueOf()
——返回当前对象对应的值,默认情况返回对象本身;它的主要用途是,js自动类型转换会默认调用这个方法:
eg:
var obj = new Object();
obj + 1//"[object Object]1"
上边代码将对象obj与数字1相加,这时js就会默认调用valueOf()方法,求出obj的值,再与1相加。。。
我们也可以自定义valueOf方法,来覆盖Object.prototype.valueOf:
var obj = new Object();
obj.valueOf = function(){
return 1;
}
obj +1 //2
Object.prototype.toString()
——返回一个对象的字符串形式,默认情况下返回该类型字符串。(简单说就是把对象转字符串)
var obj1 = new Object();
var obj2 = {name:"lxc"};
var arr = [1,2];
var str = "123";
var num = 1;
var date = new Date();
obj1.toString()//"[object Object]"
obj2.toString()//"[object Object]"
arr.toString()//"1,2"
str.toString()//"123"
num.toString()//"1"
date.toString()//"Sun Jun 23 2019 19:57:28 GMT+0800 (中国标准时间)"
上边代码中,数组、字符串、Date对象调用toString()方法,并不会返回[object,Object],因为它们都自定义了toString方法,覆盖了原始的方法。
在开发中toString()的实际应用——判断数据类型:
Object.prototype.toString()方法返回对象的该类型的字符串,因此可以用来判断一个值的类型。
eg:
var obj = {};
obj.toString()//"[object Object]"
上边代码调用空对象的toString方法,结果返回一个字符串,第二个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()方法会看出一个值到底是什么类型:
Object.prototype.toString.call(1)//"[object Number]"
Object.prototype.toString.call([])//"[object Array]"
Object.prototype.toString.call("")//"[object String]"
Object.prototype.toString.call({})//"[object Object]"
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]"
利用这个特性,可以写出一个比typeof运算符更准确的类型判断函数:(可对比 jQuery中$.type()方法)
var paramType = function(param){
var _type = Object.prototype.toString.call(param);
return _type.match(/\[object (.*?)\]/)[1].toLowerCase();
};
paramType([])//"array"
paramType(1)//"number"
paramType(null)//"null"
paramType({})//"object"
Object.prototype.toLocaleString()
——方法与toSting的返回结果相同,也是返回一个值的字符串形式。唯一不同的是toLocaleString()返回的是本地字符串形式:
eg:
var date = new Date();
console.log(date.toLocaleString())//2019/6/23 下午9:04:18
console.log(date.toString())//Sun Jun 23 2019 21:04:18 GMT+0800 (中国标准时间)
Object.prototype.hasOwnProperty()
——方法接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否有改属性。(我们知道for in是遍历对象所有可枚举的属性,原型上的或继承的属性也能遍历出来,如果只想要对象自身属性,可利用hasOwnProperty()判断下是否是自身属性。。。)
eg:
var obj = {
name:"lxc"
}
Object.prototype.age = "20";
for(key in obj){
//属性key是否是obj对象自身属性,是返回true,否返回false
if(obj.hasOwnProperty(key)){
console.log(key)//name
}
}
下边我们来看下ES6中对象的扩展功能:
1、对象属性的简写:
// ES5
function a(id){
return {
id:id
}
}
//ES6
const a = id=>{
return {
id
}
}
console.log(a(1))
2、对象方法的简写:
// ES5
var obj = {
name:function(){
alert("lxc");
}
}
//ES6
let boj = {
name(){
alert("lxc");
}
}
3、属性名可计算:
属性名可以传入变量或者常量,而不只是一个固定的字符串。
let a = 1;
let b = {
[`name${a}`]:"lvxingchen"
}
console.log(b)//{name1:"lvxingchen"}
console.log(b[`name${a}`])//"lvxingchen"
对象新增方法:
1、Object.is : 比较两个值是否相等,解决了js中 == 或者===带来的异常情况;
异常情况:
console.log(NaN == NaN)//false
console.log(5 == "5")//true
新增的Object.is解决了此问题:
console.log(Object.is(NaN,NaN))//true
console.log(Object.is(5,"5"))//false
2、Object.assign( param1 , param2 , ··· ··· ) : 实现拷贝一个对象给另外一个对象,返回一个新对象。(此方法是浅拷贝,将param2对象中可枚举的属性和方法拷贝到param1中,且会改变对象param1)
let a = {
name:"lx",
age:20
};
let b = {
say:"haha",
age:21
};
Object.assign(a,b);
console.log(a)//{name:"lx",age:21,say:"haha"}
3、ES6严格模式下,对象中出现key相同的情况,后边的key会覆盖掉前面相同的key。
ES6中对象的属性:
1、属性可简写
function f(x,y){
return {x,y};
}
// 等同于
function f(x,y){
return {
x:x,
y:y
}
}
console.log(f(1,2))//{x:1,y:2}
2、方法也可以简写:
const foo = {
say(){
console.log("hehe");
}
}
// 等同于
const foo = {
say:function(){
console.log("hehe");
}
}
模块的输出:
function a (){}
function b (){}
function c (){}
module.exports = { a, b, c };
// 等同于
module.exports = {
a:a,
b:b,
c:c
}
3、属性表达式:
const obj = {
['a' + 'b']: '123'
}
console.log(obj) // {ab: "123"}
let obj = {
["h" + "ello"](){
console.log("哈哈")
}
}
4、属性的可枚举性和遍历:
可枚举性
对象的每一个属性有一个描述对象(Descriptor),用来控制改属性的行为。
Object.getOwnPropertyDesciptor方法可以获取该属性的描述对象。
let obj = {
name:"lxc"
}
console.log( Object.getOwnPropertyDescriptor(obj,"name") );
// {
// value: "lxc",
// writable: true,
// enumerable: true,
// configurable: true
// }
描述对象的enumerable为false的属性,成为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。
目前,有四个操作会忽略enumerable为false的属性。
—— for ··· in循环:之遍历对象自身的和继承的可枚举的属性。
—— Object.keys() : 返回对象自身的所有可枚举的属性键名。
—— JSON.stringify() : 值串行化对象自身的可枚举的属性。
—— Object.assign() : 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
上边四个方法,只有for in 会返回继承的属性,其他三个方法都会忽略继承的属性,对处理对象自身属性。
另外,ES6规定,所有的Class的原型的方法是不可枚举的。。。
class Test{
constructor(){
this.name = "lxc"
}
say(){
alert("haha")
}
}
new Test()
console.log( Object.getOwnPropertyDescriptor(Test.prototype,"say").enumerable ) // false
总的来说,操作中引入继承的属性,会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不用for ··· in循环,二用Object.keys代替。。。