深入理解ES6--对象、函数扩展

12 篇文章 13 订阅

扩展对象的功能性

属性名称简写

let name = 'ligang'
let person = {
 name,
 sayName()  {
   console.log(name)
 }
}

javascript引擎会在访问作用域中查找其同名变量;如果找到,则变量的值被赋给对象字面量的同名属性。

Object.is()

Object.is()方法是为了弥补全等运算符’===’的准确性,其接受两个参数,如果两个参数类型相同且具有相同的值,则返回true。

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

console.log(NaN === NaN) // false
console.log(Object.is(NaN, NaN)) // true
console.log(isNaN(NaN)) // true

注意:map.get()底层使用的就是Object.is()进行判断获取

let myMap = new Map().set('0', 'xxx')
myMap.get(0)    // undefined
myMap.get('0')  // xxx

Object.assign()

对象组合,浅拷贝

自有属性枚举顺序

ESMAScript6严格定义了对象的自有属性被枚举时的返回顺序,这会影响到Object.getOwnPropertyNames()方法及Reflect.ownKeys返回属性的方式,Object.assign()方法处理属性的顺序也将随之改变。

  • 所有数字键按照升序排序;
  • 所有字符串按照它们被加入对象的顺序排序;
  • 所有symbol键按照它们被加入对象的顺序排序。
let obj = {
  a: 1,
  0: 1,
  c: 1,
  2: 1,
  b: 1,
  1: 1
}
Object.getOwnPropertyNames(obj) // ["0", "1", "2", "a", "c", "b"]

注意,for-in并非所有厂商都遵循相同的实现方式;Object.keys()JSON.stringify()for-in相同,所以目前也不明确!

原型访问super

let person = {
  sayHi() {
    return 'hi'
  }
}
let friend = {
  sayHi() {
    // 获取其原型方法
    return Object.getPrototypeOf(this).sayHi.call(this) + ' friend'
  }
}
let friend2 = {
  sayHi() {
    return super.sayHi() + ' friend2'
  }
}

Object.setPrototypeOf(friend, person);
friend.sayHi()  // "hi friend"

Object.setPrototypeOf(friend2, person);
friend2.sayHi() // "hi friend2"

函数

函数形参的默认值

ES5方式

function test(name) {
    name = (typeof name !== 'undefined') ? name : 'ligang'
    // name = name || 'ligang' // 当name为假值时会出现问题!!如,test(0)
    return name
}

ES6:注意,对于默认参数值,null是一个合法值

function test(name = 'ligang') {
    return name
}
test(undefined) // ligang
test(null) // null

默认参数表达式

function getvalue(n) {
    return n
}
function add(first, second = getvalue(first)) {
    return first + second
}
add(100) // 200

注意:

  • getvalue()方法只有当调用add()函数且不传入第二个参数时才会调用;
  • 引用参数默认值时,只允许引用前面参数的值,即先定义的参数不能访问后面定义的参数。

展开运算符

数组

let ary = [1, 2, 3]
let max = Math.max(...ary, 5)
console.log(max) // 5

对象

let obj = {a: 1, b: {c: 2}}
let obj2 = {...obj}
obj.b.c = 3
console.log(obj2) // {a: 1, b: {c: 3}} 浅拷贝

特别说明:
ES6中展开运算符只针对iterable才起作用,默认有数组、set、map和字符串。并不包含对象!ES6规范中也并未将展开运算符支持对象,但是目前的主流浏览器Chrome和firefox均已实现该特性。这意味着如果想在低版本浏览器中使用需要特别的Babel插件进行转换!object-rest-spread
object-rest-spread

明确函数的多重用途

JavaScript函数有两个不同的内部方法:[[Call]][[Construct]](构造函数)。通过new关键字调用函数时,执行的是[[Construct]]函数,将this绑定到实例上;如果不通过new调用,则执行[[Call]]函数

function Person(name) {
    if (this instanceof Person) {
        this.name = name
    } else {
        throw new Error('必须通过new关键词创建')
    }
}
let p = new Person('ligang')
Person.call(p, 'lee') // 不会报错

所以,我们无法区分通过Person.call()(或Person.apply())调用还是new关键字创建!

元属性new.target可以解决,调用[[call]]方法,new.target的值为undefined。

function Person(name) {
    if (typeof new.target !== 'undefined') {
        this.name = name
    } else {
        throw new Error('必须通过new关键词创建')
    }
}
let p = new Person('ligang')
Person.call(p, 'lee') // 必须通过new关键词创建

箭头函数

  • 没有this、super、arguments河new.target绑定;
  • 不能通过new关键字调用;
  • 没有原型;
  • 不可以改变this的绑定;

    如果箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this;否则,this的值会被设置为undefined。

let person = {
    name: 'ligang',
    sayName() {
        return (() => this.name)()
    }
}
  • 不支持重名的命名参数。

尾调用优化

ES6对尾调用(函数作为另一个函数的最后一条语句被调用)进行了优化。ES5中,尾调用实现为“创建一个新的栈,将其推入调用栈来表示函数调用,即未用完的栈都在内存中,当调用栈变大会造成程序内存溢出”。ES6中不在创建新栈,会清除并重新利用当前栈。

  • 尾调用不访问当前栈的变量(即不是一个闭包);
  • 在函数内部,尾调用是最后一条语句;
  • 尾调用的结果作为函数值返回。
function factorial(n) {
    if (n <= 1) {
        return 1
    }
    return n * factorial(n - 1)
}

优化后

function factorial(n, p = 1) {
    if (n <= 1) {
        return 1 * p
    }
    let result = n * p
    return factorial(n - 1, result)
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋飛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值