对象

JavaScript中的对象

Object每个实例的方法

  1. constructor:构造函数
  2. hasOwnProperty(propertyname):检查该属性在对象实例中是否存在(不检查原型)
  3. isPrototypeOf(obj):检查传入的对象是不是当前对象的原型
  4. propertyIsEnumerable(propertyname):检查该属性是否可枚举
  5. toLocalString(),toString(),valueOf():返回对象的字符串表示/数值表示

属性类型——描述属性各种特征

ES有两大类型属性:数据属性、访问器属性

  1. 数据属性
    [[configurable]]:能否通过delete删除属性
    [[enumerable]]:是否可枚举
    [[writable]]:是否可修改
    [[value]]:属性值

    ES5可以通过使用 Object.getOwnpropertyDescriptor() 来获取属性的特征描述
    使用 Object.defineProperty() 修改默认属性,接收三个参数:属性所在对象、属性名、描述对象

  2. 访问器属性
    [[configurable]]:能否通过delete删除属性
    [[enumerable]]:是否可枚举
    [[Get]]:在读取属性时调用,默认为undefine
    [[Set]]:在写入属性时调用,默认为undefine
    常见用途:修改一个属性值时让关联的另一个属性发生变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var book = {
year:2019,
edition:1
}
Object.defineProperty(book, 'year', {
get:function(){
return this.year
},
set:function(NewY){
this.year = NewY
edition += 1
}
})
book.year = 2020
book.edition //2

属性名表达式

ES6允许在使用字面量定义对象时,将表达式作为属性名

1
2
3
4
5
6
7
8
9
10
11
12
var last = 'last'
var a = {
first:'first',
[last]:'last'
}
console.log(a.first) //first
console.log(a['first'])//first
console.log(a.[first])//error

console.log(a.last)//last
console.log(a[last])//last
console.log(a['last'])//last

注意:若属性名表达式是一个对象,默认情况下会把属性转换为:[object,object]。一个对象只能有一个对象属性名,多余的会被最后一个覆盖

1
2
3
4
5
6
7
8
const a = {a:1}
const b = {b:2}
const c = {
[a]:1,
[b]:2
}
console.log(c)
//{[object,object]:2}

方法的name属性

该属性是函数的属性,返回函数名

1
2
3
4
5
6
const p = {
sayname(){
console.log('tom')
}
}
console.log(p.sayname.name)//sayname

对于用bind产生的函数,会在名字前加上“bound”

1
2
var fun = function(){...}
console.log(fun.bind().name)//"bound fun"

Object.is()

用同值相等算法比较两个值严格相等
对于es5中的 “ == ” 和 “ === ”,前者会自动转换数据类型,后者NaN不等于自身,因此ES6提供了新方法判断两个值严格相等

1
2
3
4
5
6
7
Object.is('foo','foo')//true
Object.is({},{})//false

+0 === -0 //true
Object.is(+0, -0) // false
NaN === NaN //false
Object.is(NaN, NaN) //true

Object.assign()

将源对象所有可枚举属性复制到目标对象,第一个参数是目标对象, 后面所有参数都是源对象。

1
2
3
4
5
var target = {a:1}
var source = {b:2}
Object.assign(target, source)
//target:
//{a:1, b:2}

当目标对象与源对象有重名属性,或多个源对象之间有重名属性,则后面的属性会覆盖之前的属性。

1
2
3
4
5
6
var target = {a:1}
var source = {b:2}
var source1 = {b:3}
Object.assign(target, source, source1)
//target:
//{a:1, b:3}

对于Object.assign()的参数

  1. 只有一个参数,直接返回参数
  2. 该参数不是对象,则转化为对象
  3. 参数为undefine或null,报错
  4. 非对象出现在非首参数(源对象)位置,只有字符串会以数组形式复制到目标对象当中,其他值无效
    1
    2
    3
    var v1 = 'abc'
    var obj = Object.assign({}, v1)
    //{0:'a', 1:'b', 2:'c'}
    注意:该方法不复制对象的继承属性和不可枚举属性
    该方法使用的是浅复制
1
2
3
4
5
6
var obj1 = {a:1}
var obj2 = Object.assign({}, obj1)
obj2 //{a:1}
obj1.a.b = 3
obj2 //{a:{b:3}}
//obj2得到的是obj1的引用

应用于数组

既然数组实际上是对象,数组实际的存储是这样的
{
‘1’ : ‘a ,
‘2’ : ‘b’,
‘3’ : ‘c’
}
所以对于数组的处理就比较特殊

1
2
Object.assign([1,2,3], [4, 5]) 
//[4, 5, 3]

Object.assign的用途

  1. 给对象添加属性
1
2
3
4
5
class point{
constructor(x, y){
Object.assign(this, {x, y})
}
}
  1. 给对象添加方法
1
2
3
4
5
6
var obj = {}
Object.assign(obj.prototype, {
fun1(arg){...},
fun2(arg){...},
...
})
  1. 克隆对象
1
2
3
4
5
6
7
8
9
function clone(obj){
return Object.assign({}, obj)
}

//若要连带拷贝其继承属性
function clone(obj){
var proto = obj.__proto__
return Object.assign({}, Object.create(proto, obj))
}
  1. 合并多个对象
1
const merge = (...sou) => {return Object.assign({}, ...sou)}
  1. 为属性指定默认值
1
2
3
4
const default = {a:1, b:2}
function fun(option){
Object.assign({}, default, option)
}

属性的描述对象

前面已经提到, ES5可以通过使用 Object.getOwnpropertyDescriptor() 来获取属性的特征描述

1
2
3
4
5
6
7
8
9
10
var obj = {foo: 123}
Object.getOwnPropertyDescriptor(obj, 'foo')
/*
{
value:123,
writable:true,
enumerable:true,
configurable:true
}
*/

ES6规定:所有class的原型方法都是不可枚举的

ES6提供了Object.getOwnpropertyDescriptor(),返回所有对象属性的描述对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var obj = {
foo:123,
get fun(){
return 'abc'
}
}
Object.getOwnpropertyDescriptors(obj)
/*
{
foo:{
value:123,
writable:true,
enumerable:true,
configurable:true
},
fun:{
get:[Function:fun],
set:undefine,
enumerable:true,
configurable:true
}
}
*/

属性的遍历

  1. for…in:遍历自身和继承的所有可继承属性
  2. Object.key(obj):返回数组,包含对象自身的所有可枚举属性
  3. Object.getOwnPropertyName(obj):返回数组,包含对象自身所有属性(不含symbol)
  4. Object.getOwnPropertySymbol(obj):返回数组,包含对象自身所有symbol属性
  5. Reflect.OwnKeys(obj):返回数组,包含对象自身所有属性

    这些遍历对象属性的方法均遵守:

  6. 属性名为数字,按数字排序
  7. 属性名为字符串或symbol,按生成顺序排序
  8. 若三者混合,则按数字 -> 字符串 -> symbol排序

Object.key()

es5引入的该方法,返回一个数组,成员是参数自身的所有可枚举属性的键名

Object.values()

返回一个数组,成员是参数自身的所有可遍历属性属性的键值

Object.entries()

返回一个数组,成员是参数自身的所有克遍历属性的键值对数组

proto

用来读取设置当前对象的prototype对象。
注意:这不是一个正式的对外开放的API,只不过广大浏览器支持了这个属性。
一般建议使用Object.getPrototypeOf()

Object.getPrototypeOf()和Object.setPrototypeOf()

ES6推荐使用Object.setPrototypeOf()设置对象的原型,使用Object.getPrototypeOf()读取对象原型
关于后者的参数

  1. 若是Number,String,boolean,则之间返回参数
  2. 若是undefine,null,则报错

对象的扩展运算符

对象的解构赋值

将对象可遍历却又未读取的属性分配到指定的对象上面

1
2
3
4
var {x, y, ...z} = {x:1, y:2, a:3, b:4, c:5}
x//1
y//2
z//{a:1, b:2, c:3}

解构赋值等号右边不能是undefine或null,否则直接报错

1
2
3
var {x, y, ...z} = undefine
var {x, y, ...z} = null
//统统报错

注意:结构赋值的复制过程是浅复制,如果一个键的值是引用类型,那么解构赋值得到的是这个值的引用,同时,结构赋值也不会赋值继承自原型对象的属性

1
2
3
4
5
6
7
8
9
10
11
var obj = {a:1, b:2}
var a = {...obj}
obj.a = 5
console.log(a)
//1

var obj1 = {a:1, b:2, c:{d:3}}
var b = {...obj1}
obj1.c.d = 6
console.log(b)
//{a:1, b:2, c:{d:6}}

取出参数对象所有可遍历属性

类似于Object.assign()的操作,也不能复制其继承属性

1
2
3
let z  ={a:3, b:4}
let k = {...z}
//k:{a:3, b:4}

稍作改进也可以复制其继承属性

1
2
let z  ={a:3, b:4}
let k = {...Object.create(Object.getPrototypeOf(z)),...z}

他有和Object.assign()类似的作用

克隆对象

1
2
3
4
5
let z  ={a:3, b:4}
z.__proto__.name = 'z'
let k = {...Object.create(Object.getPrototypeOf(z)),...z}
console.log(z)
console.log(k)

在这里插入图片描述

合并对象

1
2
3
4
5
6
let a = {x:1}
let b = {y:2}
let ab = {...a, ...b}

//等价于
let ab = Object.assign({}, a, b)

扩展运算符后面的属性值会覆盖扩展运算符中的同名属性,同assign

添加默认值

将用户定义的默认值放在运算符前面,就可以为对象设置默认值

1
2
3
4
let default = {x:1, y:2, ...a}

//等同于
let default = Object.assign({}, {x:1, y:2}, a)

对象的扩展运算符后面可以带有表达式

1
2
3
4
var obj = {
...(x > 1 ? {x:1} : {y:2}),
b:2
}

对象扩展运算符的参数为null或undefine时,这两个值会被忽略,不会报错

1
2
3
4
5
var a
var b = null
var c = {...a}
var d = {...b}
//均不报错
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2015-2021 AURORA_ZXH
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信