Es6对象的扩展

属性的简写方法

var name = '秦司令';
var json = {name} // name:'秦司令'

上面代码中,变量在对象中当做属性名,属性值就是变量的值,这就是属性的简写方式。


var age = 19
var obj = {
   name:'秦司令',  
   age
}
console.log(obj) // {name:'秦司令',age:19}

函数中的声明的对象也能简写

function example(x,y){
  return {x,y}
}
console.log(example(1,2)) // {x:1,y:2} 

上面代码如果不传参,x和y的参数就是undefined。


对象里面的函数也可以简写。

var json = {
  add(){
    alert(1)
  }
}
// 上面的方法等同于下面
var json = {
  add:function(){
    alert(1)
  }
}

简写一个Generator函数,前面需要要加上 * 号

var obj = {
    * add(){
      yiled 'hello word'
    }
}

上面代码中,Generator函数等下一期跟你们分享,详细讲解。

属性名表达式

js定义对象有两种方式

var obj = {}
obj.name = '秦司令';
obj['a' + 'ge'] = 19;

上面代码中,方法一是用标识符作为对象属性名,方法二是用表达式作为属性名,这是将表达式方在中括号内,中括号内可以写变量,请看下面代码。

let age = 'age';
var json = {
  [age] :19,
  ['a' + 'bc'] : 123
}
console.log(json) // {age:19,abc:123}

表达式还可以用于定义方法名。

var obj = {
    ['a' + 'bc'](){
        return 'abc'
    }
}
console.log(obj.abc()) // abc

注意,对象的简写不能和表达式一起使用,会报错。

var name = '秦司令';
console.log({ [name] }) // 报错
console.log({ [name] : 123 }) // 秦司令:123

如果属性表达式是一个对象的话,默认情况下会自动转为字符串,[object Object] 。

var dx = {}
var json = {
  [dx]:123
}
console.log(json) // {[object Object] :123}

方法name的属性

函数的name属性,返回函数名,对象方法也是函数,因此也有name属性。

var obj = {
  add(){
    return 123
  }
}
console.log(obj.add.name) // add

上面代码,方法add的name属性就是函数名,add。


函数name属性有两种特殊情况,bind方法创造的函数,name属性返回 bound 加上函数名 ;Function 构造函数创造的函数,name属性返回anonymous 英语意思为(匿名的)

(new Function()).name // anonymous
function abc(){}
console.log(abc.bind().name) // bound abc 

如果对象方法是一个Symbol值,那么name属性返回的就是这个Symbol值的描述。

var s = Symbol('foo')
var s1 = Symbol()
let obj = {
  [s](){},
  [s1](){}
}
console.log(obj[s].name) // ['foo']
console.log(obj[s1].name) // ""

上面代码中,s对应的Symbol值有描述,s1没有

属性的可枚举性和遍历

可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

let obj = {foo:123};
Object.getOwnPropertyDescriptor(obj,'foo');
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }

描述对象的enumerable属性称为 "可枚举性" , 如果该属性为false,就表示某些操作会忽略当前属性。


目前,有四种操作会忽略enumerable为false属性
for..in循环:只遍历对象自身和继承的可枚举性的属性
Object.keys() : 返回对象自身的所有可枚举属性的键名
JSON.stringify() : 只转换自身的可枚举性的属性
Object.assign() : 忽略enumerable为false的属性,只拷贝对象自身的可枚举性的属性

var json1 = {name:'秦司令'}
Object.defineProperty(json1,'age',{
    value:19,
    enumeable:false
})
for(var i in json1){
    console.log(i)   // name 
};
console.log(Object.keys(json1)) // ['name']
console.log(JSON.stringify(json1))  // {"name":"秦司令"}
console.log(Object.assign({},json1))  // {name: "秦司令"}

上面代码中,都获取不到enumerable为false的属性,Object.defineProperty是专门设置描述对象的属性;

属性的遍历
Object.getOwnPropertyNames(obj)

该方法返回一个数组,包含自身的所有属性(不包含Symbol属性,但是包括不可枚举属性)的键名

var json1 = {name:'秦司令'}
Object.defineProperty(json1,'age',{
    value:19,
    enumeable:false
})
console.log(Object.getOwnPropertyNames(json1)) // ["name", "age"]
Object.getOwnPropertySymbols(obj)

该方法返回一个数组,包含对象自身的所有 Symbol 属性的键名,只返回Symbol的键名。

var jsonArr = {[Symbol('123')]:1,b:2,c:9,3:'d',[Symbol()]:123}
console.log(Object.getOwnPropertySymbols(jsonArr)) //  [Symbol(123), Symbol()]
Reflect.ownKeys(obj)

该方法返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

var jsonArr = {[Symbol('123')]:1,b:2,c:9,3:'d',[Symbol()]:123}
console.log(Reflect.ownKeys(jsonArr)) // ["3", "b", "c", Symbol()]

上面代码中,Reflect.ownKeys该方法返回一个数组,返回所有的属性,这个数组的顺序是这样的,首先是数值属性,然后是字符串,按照字符串的位置加入,最后是Symbol属性

super关键字

Object.prototype.name = 'lider'
var json = {
    name:'我是json',
    add(){
        return super.name;
    }
}
console.log(json.add());

上面代码中,super该方法是指向Object的原型。


看下面的列子

var obj = {
    name:'我是obj',
    na(){
          console.log(this.name)
    }
}

var json = {
    name:'我是json',
    add(){
        return super.name;
    }
}

Object.setPrototypeOf(json,obj)
console.log(json.add()); // 我是obj

上面的代码,把json的原型改成了obj的原型,所以name属性就指向obj里面的。


super该方法现正只能,用在对象的简写方法内容。

// 报错
const obj = {
  foo: super.foo
}

// 报错
const obj = {
  foo: () => super.foo
}

// 报错
const obj = {
  foo: function () {
    return super.foo
  }
}

对象的扩展运算符

Es2018将扩展运算符引入了对象。

var [a...b] = [1,2,3]
a //1
b // 2 3 

解构赋值

对象的解构赋值用于从一个对象取值,相当于将目标对象自身所有可遍历属性(包括enumerable),但尚未被读取的属性,分配到指定的对象上面,所有的键和它们的值,都会拷贝到新对象上面。

let {x,y...z} = {x:1,y:2,c:3,d:4}
x // 1
y // 2
z // {c:3,d:4}

上面代码中,变量z是解构赋值所在的对象,它获取等号右边尚未读取的值,并且将(键值和属性值) 一同拷贝过来


解构赋值要求等号右边必须是对象,如果不是对象,就会强制转换为对象,undefined和null无法转换为对象,所以它们会报错。

let {...z} = null;
let {...a} = undefined

解构赋值必须最后一个参数是扩展运算符,否则会报错。

let {...a,b} = {a:1,b:2}

注意,解构赋值的拷贝是浅拷贝,即如果一个键值的是数组或者是对象,那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。

let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2

另外,扩展运算符的解构赋值,不能复制继承的原型。

let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined

如果扩展运算符后面是一个对象,则没有任何效果。

console.log( {...{} , a:123 } ) // {a:123}

如果扩展运算符后面不是对象,则会自动将其转为对象。

console.log({...1}) // {}

上面代码中,将其转换为对象 包装类Number{1} ,因此它没有属性则返回空对象。


如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象。

{...'hello'}
// {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}

扩展运算符的参数之中,如有取值函数get,这个函数是会执行的。

let abc = {
    get aa(){
        return 1
    }
}
console.log(abc)

let abc1 = {
    ...{
        get aa(){
            return '我自动执行'
        }
    }
}
console.log(abc1)
希望看完这篇文章,能对你有所收获!
如有不正确的地方,望大神指点。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 属性的简介表示法 varfoo ='bar'; varbaz = {foo}; baz//{foo: "ba...
    ningluo阅读 2,166评论 0 0
  • 属性的简洁表示法 ES6允许直接写入变量和函数,作为对象的属性和方法。 上面代码表明,ES6允许在对象之中,直接写...
    oWSQo阅读 3,462评论 0 0
  • 1.属性的简洁表示法 允许直接写入变量和函数 上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量...
    雨飞飞雨阅读 4,849评论 0 3
  • 1.属性的简介表示法 const foo ='bar' const baz = {foo} baz //{foo:...
    yfsola阅读 1,586评论 0 0
  • 江湖的另一端,曾在鄱阳湖上喝酒纵歌的年轻小哥刘休范初长成。 刘休范是孝武帝之侄,但他貌似资质愚钝,从小就在长辈兄弟...
    惘然生烟阅读 3,966评论 0 4