ES6对象

属性的简洁表示法
  • ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
const foo = 'bar';
const baz = {foo};
baz      // {foo: "bar"}
// 上面代码中,变量foo直接写在大括号里面。这时,属性名就是变量名, 属性值
//就是变量值
  • 除了属性简写,方法也可以简写。
// 在定义一个对象里面应用里面应用
const obj = {
  method() {
    return "Hello!";
  }
};

// 等同于
const obj = {
  method: function() {
    return "Hello!";
  }
};
--------------------------------------------------------------------
// 在定义一个类里面应用
class Ser{
    clear(){
        console.log("测试1")
    }
    clear = function() {
        console.log('测试1')
    }
}
let Serious = new Ser()
Serious.clear()
  • 注意,简写的对象方法不能用作构造函数,会报错。
const obj = {
  f() {
    this.foo = 'bar';
  }
};

let obj2 = new obj.f() // 报错

属性名表达式
  • ES6 允许字面量定义对象时,用表达式作为对象的属性名。
let lastWord = 'last word';
const a = {
  'first word': 'hello',   // ES5 的写法
  [lastWord]: 'world'      // Es6 的写法
};

a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
const keyA = {a: 1};
const keyB = {b: 2};

const myObject = {
  [keyA]: 'valueA',
  [keyB]: 'valueB'
};

myObject // Object {[object Object]: "valueB"}
// 上面代码中,[keyA]和[keyB]得到的都是[object Object],
// 所以[keyB]会把[keyA]覆盖掉,而myObject最后只有一个[object Object]属性

方法的 name 属性
const person = {
  sayName() {
    console.log('hello!');
  },
};
person.sayName.name   // "sayName"
// 方法的name属性返回函数名(即方法名)
  • 有两种特殊情况:bind方法创造的函数,name属性返回bound加上原函数的名字;Function构造函数创造的函数,name属性返回anonymous
// 构造函数
(new Function()).name // "anonymous"

// bind()方法创建函数
var doSomething = function() {
  // ...
};
doSomething.bind().name // "bound doSomething"
// bind()函数的作用是将函数的 this 锁定,不会因不同的调用而改变 this的值
属性的可枚举性和遍历

ES6 一共有 5 种方法可以遍历对象的属性。

(1)for…in

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。(比较常用)

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。

(5)Reflect.ownKeys(obj)

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

let newPerson = {
    name:'Jack',
    age: 18,
    school:'Gdufs',
    grade:'University',
    index(){
        console.log('this is a great person!')
    }
}
// 遍历对象
console.log(Object.keys(newPerson))  //["name", "age", "school", "grade", "index"]

super 关键字
  • super关键字用于访问和调用一个对象的父对象上的函数。
  • ·注意,super关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
  • 原型对象:函数的内置属性prototype(指针)指向原型对象,实例对象通过_ptoto_指向原型对象。
  • 假设var s = new student() => s.__ptoto__ = student.prototype 这个关系式成立
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
// o2 的原型对象是 o1

在对象字面量中使用super.prop

const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};
Object.setPrototypeOf(obj, proto);  // 为 obj 设置原型对象 proto
// 所以 super.foo 可以引用到 proto 里面的方法
obj.find() // "hello"

扩展运算符
  • 解构赋值的经典例子
const o = Object.create({ x: 1, y: 2 });
o.z = 3;

let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3
// 出现这种情况的原因:扩展运算符(...)只能够继承 赋值对象的属性而不能够
// 继承原型对象的属性,Object.create({x:1, y:2})是为 o 对象指定原型对象,
// 而 o 本身的属性就只有 z,所以会出现这样的结果。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }

// 对象嵌套对象数组的解构
let objc = {name:'Ming',age:18}
console.log({...objc})   //  {name: "Ming", age: 18}
console.log({...['a', 'b', 'c']})   // {0: "a", 1: "b", 2: "c"}

//扩展运算符可以用于合并两个对象。
let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
  • 如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。
let a = {x:2, y:3}
let aWithOverrides = { ...a, x: 1, y: 2 };
console.log(aWithOverrides)    //{x: 1, y: 2}  覆盖掉原来的属性
  • 与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式
let x = 2
const obj = {
  ...(x > 1 ? {a: 1} : {}),
  b: 2,
};
obj // => {a:1, b:2}

链判断运算符
let jsc = {name:'Nacy', age:18}
let able = jsc?.name  // Nacy  在判断jsc != null /undefined 后执行 jsc.name 

?.运算符,直接在链式调用的时候判断,左侧的对象是否为null或undefined。如果是的,就不再往下运算,而是返回undefined

const firstName = message?.body?.user?.firstName || 'default';
// 他会沿 从左向右的方向进行判断

链判断运算符有三种用法。

  • obj?.prop // 对象属性
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法的调用

下面是这个运算符常见的使用形式,以及不使用该运算符时的等价形式。

a?.b
// 等同于
a == null ? undefined : a.b
a == null || undefined ? undefined : a.b
// 这两种写法没有区别,因为在 javascript里面, null == undefined => true
// 但是注意 undefined === null => false

a?.[x]
// 等同于
a == null? undefined : a[x]

a?.b()
// 等同于
a == null ? undefined : a.b()

a?.()
// 等同于
a == null ? undefined : a()
  • 如果属性链有圆括号,链判断运算符对圆括号外部没有影响,只对圆括号内部有影响。
(a?.b).c
// 等价于
(a == null ? undefined : a.b).c
// 上面代码中,?.对圆括号外部没有影响,不管a对象是否存在,圆括号后面的.c总
//是会执行。
  • 右侧不得为十进制数值
    => 如果?.后面紧跟一个十进制数字,那么?.不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。

null判断运算符

ES2020 引入了一个新的 Null 判断运算符??。它的行为类似 ||,但是只有运算符左侧的值为null或undefined时,才会返回右侧的值。

  • ?? 有一个运算优先级问题,如果与 && 或者 || 混合使用的话要添加括号来标识谁先谁后。
(lhs && middle) ?? rhs;
lhs && (middle ?? rhs);
// 先执行括号内的再执行括号外的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值