属性名表达式
定义对象的属性有两种形式
1、间接应用标识符作为属性名 obj.name
2、以表达式作为属性名 obj['a'+'b'] = 10
let obj = {}
obj.name = '孙悟空' // 孙悟空
obj['a' + 'b'] = 10 // 10
console.log(obj); // {name: '孙悟空', ab: 10}
es5
中字面量定义对象只能应用一种办法
var obj2 = {name:'西方',age:10}
es6
容许应用表达式属性名,将表达式放入 方括号
内即可
let key = 'address'
let obj3 = {
name:'不败',
[key] : '武汉',
['a'+'ge'] : 100
}
console.log(obj3); // {name: '不败', address: '武汉', age: 100}
console.log(obj3.address); // 武汉
console.log(obj3[key]); // 武汉
表达式还能够定义方法名
let obj4 = {['f'+'n'](){console.log('hello');
},
fn2 : function(){ console.log('word') }
}
obj4.fn() // hello
obj4.fn2() // word
留神:解构与属性名表达式不能同时应用
// 报错
let fan = 'name'
let tion = {[fan] }
属性名表达式如果是 对象
,会被转换成字符串[object object]
let o = {a : 1}
let o2 = {b : 2}
let obj5 = {[o] : '东方不败',
[o2] : '东方求败'
}
console.log(obj5); // {[object Object]: '东方求败'}
因为属性名表达式都被转换为[object Object]
,同键名的会被笼罩,所以这里只输入最初一个{[object Object]: '东方求败'}
name 属性
函数的 name
属性返回函数名,对象办法也是函数,因而也有 name
属性
let n = {sayHi(){console.log('hello');}
}
console.log(n.sayHi.name); // sayHi
如果对象的办法应用了取值函数:getter
或存值函数 setter
,那么的属性在形容对象的get
和set
身上,须要在办法名前假 get
和set
let n2 = {get fn(){},
set fn(x){}}
let desc = Object.getOwnPropertyDescriptor(n2,'fn')
console.log(desc.get.name); // get fn
console.log(desc.set.name); // set fn
console.log(n2.fn.name); // 报错 Cannot read properties of undefined (reading 'name')
如果对象的办法是一个 Symbol
值,name
属性返回的是 Symbol
值的形容
let key1 = Symbol('desc')
let key2 = Symbol()
let kobj = {[key1](){},
[key2](){}
}
console.log(kobj[key1].name); // [desc]
console.log(kobj[key2].name); // ""
key1
有形容,返回形容 [desc]
;key2
没有值,返回空
属性的可枚举性和遍历
对象的每个属性都存在一个形容对象,用来管制该属性的行为
获取属性形容对象的办法:Object.getOwnPropertyDescriptor()
let d = {a : 123}
console.log(Object.getOwnPropertyDescriptor(d,'a'));
//{value: 123, writable: true, enumerable: true, configurable: true}
我的项目 | value |
---|---|
enumerable | true 为可枚举,false 为不可枚举 |
configurable | true 为则此个性可被删除也可被批改,false 则 不能够 |
writable | true 为能够被批改,false 为只可读 |
留神 | 用“罕用的形式”创立一个属性时,它们默认都为true |
上面四个操作会疏忽 enumerable
为false
属性
1、for...in
循环:只遍历对象本身的和继承的可枚举属性
2、Object.keys()
:返回对象本身的所有可枚举的属性的键名
3、JSON.stringify()
:只串行化对象本身的可枚举属性
4、Object.assign()
:疏忽enumerable
为false
的属性,只拷贝对象本身的可枚举属性。
其中 for...in
会返回继承的属性,其它的几个都会疏忽继承的属性
如果枚举属性为 false
,这四个办法遍历时会疏忽为false
的属性
对象遍历办法
办法 | 阐明 |
---|---|
for…in | 循环遍历对象本身和继承的可枚举属性(不含 Symbol) |
Object.keys | 返回一个数组,该数组为对象本身的所有可枚举属性(不含继承属性和 Symbol 属性) |
Object.values() | 返回一个数组,蕴含对象键值的数组(不含继承属性和 Symbol 属性) |
Object.entries() | 返回一个数组,蕴含对象键名和键值的数组(不含继承属性和 Symbol 属性) |
Object.getOwnPropertyNames | 返回一个数组,蕴含对象本身的所有(蕴含不可枚举)属性(不含 Symbol 属性) |
Object.getOwnPropertySymbols | 返回一个数组,只蕴含对象本身的所有 Symbol 属性的键名 |
Reflect.ownKeys | 返回一个数组,蕴含对象本身的(不含继承)所有键名,(含 Symbol、字符串、不可枚举属性) |
上面是这些遍历办法的演示
定义对象
let s = Symbol('sym') // Symbol 类型
let f = {a:1, b:2, c:3, d:4, e:5, [s]:6}
for…in
for (k in f) {
// 键名
console.log(k); // a b c d e
// 属性
console.log(f[k]); // 1 2 3 4 5
}
Object.keys 返回对象键名数组
console.log(Object.keys(f)); // ['a', 'b', 'c', 'd', 'e']
Object.keys(f).forEach(el => console.log(el)) // a b c d e
Object.values 返回对象键值的数组
console.log(Object.values(f)); // [1 , 2 , 3 , 4 , 5]
Object.values(f).forEach(el => console.log(el)) // 1 2 3 4 5
Object.entries 返回对象键名和键值的数组
console.log(Object.entries(f)); // [['a',[1]] , ['b',[2]] , ['c',[3]] , ['d',[4]] , ['a',[5]] ]
Object.entries(f).forEach(el => console.log(el)) // ['a',[1]] ['b',[2]] ['c',[3]] ['d',[4]] ['a',[5]]
Object.getOwnPropertyNames
console.log(Object.getOwnPropertyNames(f)); // ['a', 'b', 'c', 'd', 'e']
Object.getOwnPropertySymbols
console.log(Object.getOwnPropertySymbols(f)); // [Symbol(sym)]
Reflect.ownKeys
console.log(Reflect.ownKeys(f)); // ['a', 'b', 'c', 'd', 'e', Symbol(sym)]
留神:Symbol 是不可枚举的
let desc2 = Object.getOwnPropertyDescriptor(f,s)
console.log(desc2); // {value: 6, writable: true, enumerable: true, configurable: true}
// 在这里返回的是 enumerable:true,返回的是对象的枚举属性,并不是 Symbol
// Symbol 是不可枚举的,所以 keys 遍历中没有 Symbol
解构赋值和残余运算符
解构:能够依据对象的键名间接获取到键值,十分不便
let {a,b,...z} = {a:1, b:2, c:3, d:4, e:5}
console.log(a,b,z); // 1 2 {c: 3, d: 4, e: 5}
let info = {
id:1,
name:'东方不败'
}
let {id ,name} = info
console.log(id,name); // 1 '东方不败'
// 重命名
let {id ,name : user} = info
console.log(id,user); // 1 '东方不败'
解构赋值能够嵌套
-
单层嵌套
let infos = { vals : 1, users: {names : '东方不败'} } let {vals ,users:{names} } = infos console.log(names); // 东方不败
-
多层嵌套
let info2 = { val:1, user:{ id2:100, name2:'东方不败', address:{ city:'武汉', district : '世界城广场' } } } let {val,user:{id2,name2,address:{city,district}} } = info2 console.log(val,id2,name2,city,district); // 1 100 '东方不败' '武汉' '世界城广场'
对象的残余运算符能够将字符串转换成
键值对
的对象,键名默认从数字0
开始,顺次排列
console.log({...'world'}); // {0: 'w', 1: 'o', 2: 'r', 3: 'l', 4: 'd'}
对象的残余运算符相当于是 Object.assign()
,但这两个是 不相等
的
let r = {id : 1, name:'西方', text:'不败'}
let res = {...r}
let res2 = Object.assign({},r)
console.log(res); // {id: 1, name: '西方', text: '不败'}
console.log(res2); // {id: 1, name: '西方', text: '不败'}
console.log(res == res2); // false
残余运算符拼接,反复的键名会被笼罩
let r2 = {a:1 , b:2 , c:3 , d:4}
let r3 = {c:6,d:7,e:8,f:9}
console.log({...r2,...r3}); // {a: 1, b: 2, c: 6, d: 7, e: 8,f: 9}
对象内函数
对象内不仅能够定义一般的数据类型如:字符串、数字、数组,还能够 定义函数
,对象内函数的行为跟一般函数雷同,一般函数和箭头函数在对象内都能够定义,函数的调用形式: 对象名. 办法
let fn = {
title:'东方不败',
sayHi(){console.log('hello')},
getSum(x){return x % 2 == 0 ? true : false},
getNum : s = (x) => x + 1
}
console.log(fn.title); // 东方不败
fn.sayHi() // hello
console.log(fn.getSum(3)); // false
console.log(fn.getSum(4)); // true
console.log(fn.getNum(1)); // 2
Object.keys()
能够遍历对象键名数组,对象内的函数会返回函数名
Object.keys(fn).forEach(el=> console.log(el)) // title sayHi getSum getNum
对象内函数的 this
对象内函数的 this
指向问题跟一般函数有一些不同
对象内函数:
一般函数:this
指向的是对象自身,也就是以后对象内的所有属性和办法。
箭头函数:this
指向为window
,因为对象不形成独自的作用域,导致箭头函数定义时的作用域是全局作用域。
window.val = '东方求败'
let fn2 = {
name : '艺术概论',
inThis(){ console.log(this.val)}, // 一般函数
inThis2(){console.log(this.name)
console.log(this);
}, // 一般函数
inThis3 : t = () => {console.log(this.val)
console.log(this);
const t2 = () => {console.log(this);
}
} // 箭头函数
}
// 一般函数
function getThis2(){console.log(this.val);
}
getThis2() // 东方求败
fn2.inThis() // undefined
fn2.inThis2() // 艺术概论 // {name: '艺术概论', inThis: ƒ, inThis2: ƒ}
fn2.inThis3() // 东方求败 // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
这里别离在对象内定义了 一般函数
和箭头函数
inThis()
输入的是 undefined
,因为对象内并没有val
这个属性,this.val
没有找到,返回 undefined
inThis2()
输入的是 艺术概论
,this.name
就是以后对象内的 name
,对象内的一般函数this
指向的是以后对象 inThis3()
为箭头函数,输入 东方求败
,对象内的箭头函数this
指向的是window
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果感觉这篇文章对你有帮忙,欢送点亮一下 star 哟