关于javascript:你知道ES6中的这些属性吗

57次阅读

共计 6780 个字符,预计需要花费 17 分钟才能阅读完成。

ES6,也称 ESMAScript2015,这个版本减少了很多好用的个性

变量申明

ES6 之前用 var 来定义变量,ES6 减少了两个变量申明的形式,别离为 const 和 let,const 用来定义常量,let 用于定义变量,补救了应用 var 来定义的破绽。

  • var 有变量晋升,在全局 / 函数中定义的变量都会被晋升到全局 / 函数的最上方,值为 undefined
  • var 没有块级作用域的概念,通过 if / for /switch 定义的变量都会被晋升到全局
  • let 定义变量,可被批改,不可被反复申明,有块级作用域
  • const 定义常量,定义时需赋值,不可被批改,不可被反复申明,有块级作用域

他们三者次要区别如下

初始化需赋值 变量晋升 反复申明 从新赋值 块级作用域 跨块拜访 跨函数拜访
var × × ×
let × × × × ×
const × × × × ×

let 和 const 在定义之前会将变量保留到变量环境中,然而不可被拜访。

let userName = 'alice'
if (true) {console.log(userName)
  let userName = 'kiki'
}

以上代码的执行后果如下

在以上代码中,通过 if 创立的块级作用中有 userName 变量,尽管全局中也有 userName 变量,然而此时块中曾经通过 let 定义曾经保留到了块的变量环境中,会间接从块中获取,但在赋值之前依然是无法访问的,所以就存在了一个【暂时性死区(temporal dead zone)】的问题

字面量加强

在对象中,属性的定义有了更简洁的形式。

  • 对象中定义的属性 key 和 value 统一时,能够合并
  • 办法简写能够去掉 function 申明
  • 对象中的属性能够通过 [] 来定义非字符串的变量
var name = 'alice'
var age = 18
var info = 'hobby'

var user = {
  name: name,
  age: age,
  eating: function () {console.log('user eating~')
  }
}
user[info + 's'] = 'swimming'

const person = {
  name,
  age,
  eating() {console.log('person eating~')
  },
  [info + 's']: 'swimming'
}

console.log(user)
console.log(person)

以上两种定义对象的形式最终成果是统一的

解构

数组解构

当咱们想要获取数组的元素时,很多时候都会通过下标值,es6 给咱们提供了一种解构的形式,通过下标值的一一对应来获取每一个元素

// 通过下标值获取元素
var names = ['alice', 'kiki', 'macus']
var x = names[0]
var y = names[1]
var z = names[2]
console.log(x, y, z)

// 解构
var [a, b, c] = names
console.log(a, b, c)

// 当只须要后两位元素时,第一个元素空着
var [, m, n] = names
console.log(m,n)

// 当只对应了一个元素时,应用残余参数搁置到一个数组里
var [x, ...list] = names
console.log(x, list)

执行后果如下

通过 babel 将 es6 代码编译成 es5 代码能够发现,数组解构还是通过下标值来获取元素

对象解构

当获取对象的 value 时,咱们通常应用 .key 或者 [key],es6 对于对象也提供了更为简便的解构的形式,需注意解构进去的变量要与 key 值绝对应

var user = {
  name: 'alice',
  age: 20
}
console.log(user.name, user.age)

var {name, age} = user
console.log(name, age)

以上两种获取属性值的形式后果统一

通过 babel 将 es6 代码编译成 es5 代码能够发现,对象解构的原理还是对象. 属性名的模式

模板字符串

在没有模板字符串之前,拼接字符串和变量须要用引号(””),代码的可读性比拟弱,减少了模板字符之后,能够间接在 “ 中写字符串,通过 ${expression} 来嵌入动静的内容

const name = 'aclie'
const age = 18
const user = 'My name is' + name + 'and i am' + age + 'years old.'
const person = `My name is ${name} and i am ${age} years old.`

console.log(user)
console.log(person)

以上两种定义变量的形式后果是统一的

“ 中还能够拼接函数的执行后果

function getAnimalName(){return 'cat'}
const animal = 'This is a' + getAnimalName()
const pet = `This is a ${getAnimalName()}`

console.log(animal)
console.log(pet)

通过 + 号拼接和模板字符串是一样的后果

“ 还能够用来调用函数,通过模板字符串来宰割传参

const name = 'aclie'
const age = 18
function foo(a, b, c, d) {console.log(a)
  console.log(b)
  console.log(c)
  console.log(d)
}
foo`1${name}2${age}3${100}`

每个模板字符串中的数据对应传入函数的一个参数,宰割的残余数据组成一个数组作为参数

模板字符串转 es5 代码的实现是通过字符串的 concat 办法进行拼接

函数的默认参数

在 es6 以前须要本人判断函数有没有入参,没有就将入参的变量赋值为一个初始化的值

function getUserInfo(name, age){
  name = name || 'kiki'
  age = age || 18
  console.log(name,age)
}
getUserInfo('', 0)

function getPersonInfo(name = 'alice', age = 18){console.log(name, age)
}
getPersonInfo('alice', 0)

如果有 || 运算符时,当传入参数为空字符串或者 0 时,将被认为是 false 后执行 || 运算符后的代码

应用函数的默认参数还能够解构对象

function getUserInfo({name, age} = {name: 'kiki', age: 18}) {console.log(name, age)
}
getUserInfo()

function getPersonInfo({name = 'kiki', age = 18} = {}){console.log(name, age)
}
getPersonInfo()

两种形式解构进去的后果是一样的

通过 babel 编译函数的默认参数发现是通过 arguments 来进行解决的

残余参数

在 es6 之前,获取函数的所有入参能够通过 arguments,es6 减少了残余参数的语法用来指代没有被对应形参的实参

function foo(a, b, ...rest) {console.log('arguments', arguments)
  console.log(a, b, rest)
}
foo(1, 2, 3, 4, 5, 6)

通过 … 的运算符来获取残余参数

arguments 和残余参数还是有一些不同之处的

  • 通过 arguments 能够获取所有的实参,而残余参数只能获取没有被对应到形参的实参,而且箭头函数中是没有 arguments 的
  • arguments 的数据结构像数组,但它并不是真正的数组,是不能够间接应用数组的办法的,而残余参数就是一个数组,可间接应用数组办法

残余参数通过 babel 编译成可兼容浏览器的 es5 语法时,是通过创立数组逐个增加通过 arguments 获取的数据

开展语法

开展语法也是通过 … 来进行对数据的操作,开展语法有三个利用场景

  • 函数调用时
  • 数组结构时
  • 构建对象字面量时(ES9 语法)
const array = [1, 2, 3]
const obj = {name: 'alice', age: 20}
const name = 'kiki'

// 函数调用
function foo(a, b, c){console.log(a, b, c)
}
foo(...array)
foo(...name)

// 数组构建
const newArr = [...array, 4, 5]
console.log(newArr)

// 构建对象字面量
const newObj = {...obj, name: 'kiki'}
console.log(newObj)

可通过开展语法开展对象、数组、字符串

须要留神的是,开展语法实际上是浅拷贝

const user = {name: 'alice', favorite: { sport: 'tennis'}}
const newUser = {...user}
newUser.name = 'kiki'
newUser.favorite.sport = 'football'
console.log(user)

user 中 favorite 属性是一个对象,由 user 通过开展语法创立的 newUser 对象批改了对象中的属性,原来的 user 对象的 favorite 属性也会更改

它们在内存中的体现如下图所示

数组和函数的开展语法通过 babel 编译比较简单,别离是通过 concat 办法和 apply 第二个参数可传数组的个性,对象的开展语法简单一些,有一些函数封装和逻辑判断,就没有截图了

数值的示意

规定了进制的示意形式

  • 二进制数据,以 0b 结尾,每一位数字最大值为 1
  • 八进制数据,以 0o 结尾,每一位数字最大值为 7
  • 十六进制数据,以 0x 结尾,A- F 示意数字 10-15,每一位数字最大值为 F
const a = 0b100
const b = 0o100
const c = 0x100

console.log(a, b, c)

最初还是会转换成十进制数据

Symbol

Symbol 示意惟一的值,是一种新的数据类型,对象中的 key 值在此之前只能应用字符串,如果 key 值雷同的状况下会进行笼罩,但应用 Symbol 就不会呈现笼罩的状况。

Symbol 定义时,还有一些注意事项

  • 通过 Symbol 申明的变量能够在括号里定义一个形容,通过 description 来获取(ES10 增加的)
  • Symbol 定义的变量即便有雷同的 descripton 也不会反复
  • Symbol.for 定义的变量在全局,可通过 Symbol.keyFor 查找,有雷同的 descrition 时指向同一个元素
  • Symbol 作为对象中的 key 值时,须要应用 [],不能应用 . 来赋值
const a = Symbol('hello')
const b = Symbol('hello')
const c = Symbol.for('alice')
const d = Symbol.for('alice')

const obj = {[a]: 'alice'
}
obj[b] = 'kiki'
Object.defineProperty(obj, c, {value: 'macus'})

console.log(a)
console.log(a.description)
console.log(a === b)
console.log(c === d)
console.log(Symbol.keyFor(a), Symbol.keyFor(c))
console.log(obj[a], obj[b], obj)

执行后果如下

Set 和 WeakSet

Set

Set 意思是汇合,相似于数组,但它存储的元素不能反复。

Set 有这些属性和办法

  • size:返回 Set 中元素的个数
  • add(value):增加某个元素,返回 Set 对象自身
  • delete(value):从 set 中删除和这个值相等的元素,返回 boolean 类型
  • has(value):判断 set 中是否存在某个元素,返回 boolean 类型
  • clear():清空 set 中所有的元素,没有返回值
  • forEach(callback, [, thisArg]):通过 forEach 遍历 set
  • 反对 for / for of 的遍历
const arr = [{name: "alice"}, 2, 3, 4, 5, 4, 3, 2, 1]
const set = new Set(arr)

set.add(0)
set.delete(3)

console.log(set.size)
console.log(set.has(1))
console.log(set)
console.log([...set])
console.log(Array.from(set))

for (let item of set) {console.log(item)
}
set.forEach(item => {console.log(item)
})

执行后果如下

WeakSet

还有一个与 Set 相似的数据结构叫 WeakSet,它和 Set 的区别在于

  • WeakSet 中只能寄存对象类型,不能寄存根本数据类型
  • WeakSet 对元素是弱援用,如果没有其余援用对某个对象进行援用,那么垃圾回收器(GC)能够对该对象进行回收

它有这些办法

  • add(value):增加某个元素,返回 WeakSet 对象自身
  • delete(value):从 WeakSet 中删除和这个值相等的元素,返回 boolean 类型
  • has(value):判断 WeakSet 中是否存在某个元素,返回 boolean 类型
const student = {grade: 4}
let person = {hobby: 'running'}
const arr = [student, person]
const weakSet = new WeakSet(arr)

weakSet.add({grade: 4})
weakSet.delete(student)
console.log(weakSet.has(student))
console.log(weakSet)

因为 WeakSet 对元素是弱援用,引入的内容可能被 GC 回收,所以是不可能遍历和应用 toString()办法获取元素的

当 set 中存储的对象由内存地址 0x100 改为指向 null 时,原来的内存地址 0x100 不会被垃圾回收器回收,因为 set 中是强援用,而 weakMap 中存储的对象由内存地址 0x200 改为指向 null 时,原来的内存地址 0x200 会被垃圾回收器回收,因为 weakSet 中是强援用

Map 和 WeakMap

Map

Map 示意字典存储映射关系,相似于对象,但对象中的 Key 数据类型只能为字符串或者 Symbol,在 Map 中就没有限度

Map 常见的属性和办法

  • size:返回 Map 中元素的个数
  • set(key, value):在 Map 中增加 key、value,并且返回整个 Map 对象
  • get(key):依据 key 获取 Map 中的 value
  • has(key):判断是否包含某一个 key,返回 Boolean 类型
  • delete(key):依据 key 删除一个键值对,返回 Boolean 类型
  • clear():清空所有的元素
  • forEach(callback, [, thisArg]):通过 forEach 遍历 Map
  • 能够通过 for of 进行遍历

const user = {name: 'alice'}
const info = {message: 'hello'}
const map = new Map()
map.set(user, info)

// map.clear()
console.log(map.size)
console.log(map.has(user))
console.log(map.get(user))
console.log(map)

map.forEach((value, key)=>{console.log(value, key)
})

for(let [key, value] of map){console.log('item', key, value)
}

执行后果如下

WeakMap

与 Map 相似,但有一些区别(与 set 和 WeakSet 中的区别相似)

  • WeakMap 的 key 只能应用对象,不承受其余的类型作为 key
  • WeakMap 的 key 对对象想的援用是弱援用,如果没有其余援用援用这个对象,那么垃圾回收器(GC)能够回收该对象

它有这些办法

  • set(key, value):在 Map 中增加 key、value,并且返回整个 Map 对象
  • get(key):依据 key 获取 Map 中的 value
  • has(key):判断是否包含某一个 key,返回 Boolean 类型
  • delete(key):依据 key 删除一个键值对,返回 Boolean 类型

因为 WeakMap 对元素是弱援用,引入的内容可能被 GC 回收,所以是不可能遍历和应用 toString()办法获取元素的

以上就是 ES6 蕴含的大部分属性,对于 js 高级,还有很多须要开发者把握的中央,能够看看我写的其余博文,继续更新中~

正文完
 0