关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

对象定义-解构-枚举属性遍历以及对象内函数

发布时间:2023-06-29 22:00:20

属性名表达式

定义对象的属性有两种方式

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] } • 1 • 2 • 3

   

属性名表达式如果是对象,会被转换成字符串[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,那么的属性在描述对象的getset身上,需要在方法名前假getset

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
enumerabletrue为可枚举,false为不可枚举
configurabletrue为则此特性可被删除也可被修改,false则不可以
writabletrue为可以被修改,false为只可读
注意用“常用的方式”创建一个属性时,它们默认都为true

下面四个操作会忽略enumerablefalse属性

1、for...in循环:只遍历对象自身的和继承的可枚举属性

2、Object.keys():返回对象自身的所有可枚举的属性的键名

3、JSON.stringify():只串行化对象自身的可枚举属性

4、Object.assign():忽略enumerablefalse的属性,只拷贝对象自身的可枚举属性。

其中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} • 1 • 2

   

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哟


/template/Home/leiyu/PC/Static