专栏首页Super 前端深入理解ES6--对象、函数扩展

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

扩展对象的功能性

属性名称简写

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

明确函数的多重用途

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)
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python3解析库lxml

    lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高

    嘘、小点声
  • oday漏洞利用简单实用

    本次资源从网络整合,一些漏洞利用的方式,没有配图比较枯燥,各位看自己的兴趣观看吧。

    网e渗透安全部
  • 数据库备份拿webshell

    数据库备份拿webshell算是比较老的web后台才有的一个漏洞,之前也做过类似的,这次偶然有机会帮朋友看来一个类似的站,所以在此分享一下。仅供学习,严守底线。

    HACK学习
  • spring源码之aop proxy

    先进入org.springframework.aop.config.AopNamespaceHandler:

    开发架构二三事
  • Web渗透之文件上传漏洞总结

    文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。常见场景是web服务器允许用户上传图片或者普通文本文件保存,而用户...

    HACK学习
  • 渗透实战 | 拿下一个智能交易网站经验分享

    然后,顺手就是启动sqlmap --tamper space2comment.py

    HACK学习
  • WebService初步使用

    删掉bin中的class之后,出现cant find the main class,解决:执行clean project->clean

    ZONGLYN
  • 指定网站入侵思路

    一个网站首先要看的地方是他的网站类型,只有观察好网站类型你才能更好的应对也才能更好的找到针对的方案。

    网e渗透安全部
  • 【JS】307- 复习 Object.assign 原理及其实现

    上篇文章介绍了赋值、浅拷贝和深拷贝,其中介绍了很多赋值和浅拷贝的相关知识以及两者区别,限于篇幅只介绍了一种常用深拷贝方案。

    pingan8787
  • 【介绍一些好用的轮子(2)】json 文件的读取

    一般来说项目都有一些配置项,配置文件常见的例如 .ini, .json, .xml 等等。除了自己读取配置文件一行一行解析外,也有一些不错的现成的轮子。

    JIFF

扫码关注云+社区

领取腾讯云代金券