关于ES6新特性的总结 1

简介: 关于ES6新特性的总结

1.let & const

1) let,作用与var类似,用于声明变量

特性:

  1. let 不能重复声明变量,var 可以重复声明变量;
  2. 块级作用域,es5中存在全局作用域、函数作用域、eval作用域;es6中引入了块级作用域,
  1. let声明的变量在块级作用域{}内有效
  2. let声明的变量不存在var的变量提升问题

举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <h2 class="page-header">点击切换颜色</h2>
        <div class="item">1</div>
        <hr>
        <div class="item">2</div>
        <hr>
        <div class="item">3</div>
    </div>
    <script>
        // 获取div对象
        let items = document.getElementsByClassName('item')
        // 遍历并绑定事件 遍历时let i
        for(let i = 0; i < items.length; i++){
            items[i].onclick = function(){
                items[i].style.background = 'pink'
            }
        }
        /*
        相当于在3个块级作用域内分别声明了i
        {
            let i = 0
            items[i].onclick = function(){
                items[i].style.background = 'pink'
            }
        }
        {
            let i = 1
            items[i].onclick = function(){
                items[i].style.background = 'pink'
            }
        }
        {
            let i = 2
            items[i].onclick = function(){
                items[i].style.background = 'pink'
            }
        }
        */
        /*
        // 遍历并绑定事件 遍历时var i
        for(var i = 0; i < items.length; i++){
            items[i].onclick = function(){
                // 修改当前元素的背景颜色
                this.style.background = 'pink' // 此处this指向’被绑定的元素对象‘,即调用该函数的对象
                // 此处不能和上文一样使用 items[i].style.background = 'pink',
                // 因为var的i不考虑块级作用域, 则相当于在全局声明了一个变量,循环结束后i=3,
                // 函数执行时向上层寻找最终得到全局变量i=3,而items[3]为undefined
            }
        }
        相当于
        {
            var i = 0
            // ...
        }
        {
            var i = 1
            // ...
        }
        {
            var i = 2
            // ...
        }
        {
            var i = 3
        }
        */
    </script>
</body>
<style>
    .item{
        width: 200px;
        height: 50px;
        border-radius: 2%;
        background-color: brown;
    }
</style>
</html>

2) const 用于声明常量

注意事项:

  1. 一定要赋初始值
  2. 一般常量使用大写(属于编程规范)
  3. 常量值不能修改
  4. 存在块级作用域
  1. 对于数组和对象的元素修改,不算做对常量的修改,不会报错(因为引用数据类型保存的是内存地址,所以声明数组和对象时可以使用const声明,以此保证其保存的内存地址不变)

2.解构赋值

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值

1) 数组的解构

const Web = ['html', 'css', 'javascript']
let [tool1, tool2, tool3] = Web
console.log('tool1-----', tool1) // html
console.log('tool2-----', tool2) // css
console.log('tool3-----', tool3) // javascript

2) 对象的解构

const liMing = {
    name: 'liMing',
    age: '22',
    tell: function(){
        console.log(`I am liMing`)
    }
}
let {name, age, tell} = liMing
console.log(name) // 'liMing'
console.log(age) // '22'
console.log(tell) // f(){...}
tell() // I am liMing

3.模板字符串

特性:

  1. (反引号)内容中可以直接出现换行符,’ '和" "中则不可以,出现会报错
  2. 可以直接进行变量拼接

4.简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法(在属性名和变量名相同的情况下),这样的书写更加简洁

let name = 'LiMing'
let tell = function(){
    console.log('I am LiMing')
}
const liMing = {
    name,
    tell,
    sayHi(){
        console.log('hello')
    }
}
// 等效于
// const liMing = {
//     name: name,
//     tell: tell,
//     sayHi: function(){
//         console.log('hello')
//     }
// }
console.log(liMing)
liMing.tell()
liMing.sayHi()

5.箭头函数

function声明的区别:

1.箭头函数this是静态的。

  • 箭头函数内的this指向上层对象;始终指向函数声明时所在作用域下的this的值,无法被call改变
  • 普通函数内的this指向调用其函数的对象
function getName(){
    console.log(this.name)
}
let getName2 = ()=>{
    console.log(this.name)
}
// 设置window对象的name属性
window.student = 'LiMing'
const student = {
    name: 'HanMei'
}
// 直接调用
getName() // LiMing
getName2() // LiMing
// call方法调用
getName.call(student) // HanMei
getName2.call(student) // LiMing

2.箭头函数不能作为构造函数实例化对象

let Person = (name, age)=>{
    this.name = name
    this.age = age
}
let me = new Person('LiMing', 20) // 报错:Uncaught TypeError: Person is not a constructor

3.箭头函数不能使用arguments变量,但是可以使用....rest

let fn = ()=>{
    console.log(arguments)
}
fn(1, 2, 3) // 报错:Uncaught ReferenceError: arguments is not defined
let fn2 = (...rest)=>{
    console.log(...rest)
}
fn2('a','b','c') // a b c

4.箭头函数的简写

① 当形参有且只有一个的时候,可以省略()

② 当代码体只有一条语句的时候,可以省略{},此时return必须省略,而且语句的执行结果就是函数的返回值

// 当形参有且只有一个的时候,可以省略`()`
let add = n => {
    return n + n
}
console.log(add(9))
// 当代码体只有一条语句的时候,可以省略`{}`,此时`return`必须省略,而且语句的执行结果就是函数的返回值
let pow = n => n*n
console.log(pow(9))

5.箭头函数的例子

箭头函数适合与this无关的回调,比如定时器setTimeout(()=>{...}, 2000)、数组的方法回调arr.filter((item)=>{...})

不适合与this有关的回调,比如dom元素的事件回调ad.addEventListener('click', function(){...}、对象内的方法定义{name: 'LiMing', getName: function(){this.name}}

例1:

// 需求-1 点击div 2s后颜色变红
// 获取元素
let ad = document.getElementById('ad')
// 绑定事件
ad.addEventListener('click', function(){
    setTimeout(function(){
        console.log(this) // 定时器里的this指向window
        this.style.background = 'brown' // 报错
    }, 2000)
})
//解决方案1
// ad.addEventListener('click', function(){
//     // 保存this的值
//     let _this = this // _this指向ad
//     setTimeout(function(){
//         console.log(_this) 
//         _this.style.background = 'brown'
//     }, 2000)
// })
// 解决方案2
// ad.addEventListener('click', function(){
//     setTimeout(()=>{
//         console.log(this) 
//         this.style.background = 'brown' // this指向函数声明时所在作用域下this的值 即ad
//     }, 2000)
// })

例2:

// 需求-2 从数组中返回偶数的元素
const arr = [1, 6, 9, 10, 100, 25]
const result = arr.filter(function(item){
    if(item %2 === 0){
        return true
    }else{
        return false
    }
})
// 可以用箭头函数
// const result = arr.filter(item => {
//     if(item % 2 === 0){
//         return true
//     }else{
//         return false
//     }
// })
// 还可以简写为
// const result = arr.filter(item => item % 2 === 0)
console.log(result)

6.函数参数的默认值设置

ES6允许给函数参数赋初始值

function add(a, b, c=10){ // 具有默认值的参数,一般位置要靠后
    return a + b + c
}
console.log(add(1,2,))

可以与解构赋值一起使用

function connect({host='127.0.0.1', port, username, password}){
    console.log(host, port)
    console.log(username, password)
}
connect({
    port: 3306,
    username: 'root',
    password: 'root',
})

7.rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments

// ES5获取实参的方式
function printStudent(){
    console.log(arguments) // arguments为一个对象
}
printStudent('LiMing','HanMeimei')
// ES6获取实参的方式
function printFriend(friend1, friend2, ...rest){ // rest参数必须放在形参列表最后,否则会报错
    console.log(friend1) 
    console.log(friend2) 
    console.log(rest) // 得到一个数组,可以使用数组api
}
printFriend('小猫','小狗','兔子','鸭子')
// 小猫
// 小狗
// ['兔子','鸭子']

8.扩展运算符

...能将「数组」转为逗号分隔的「参数序列」

注:虽然形式与rest参数类似,但是rest参数是用在函数定义时的形参位置,扩展运算符是用在函数实际调用时的实参位置

const STUDENTS = ['小明','小芳','小红']
function printStudent(){
    console.log(arguments)
}
printStudent(STUDENTS) // 参数为一个数组,数组内包含3个元素
printStudent(...STUDENTS) // 参数为3个元素

应用场景:

  1. 数组的合并
const STUDENTS1 = ['小明','小芳','小红']
const STUDENTS2 = ['小吴', '小王']
// es5写法
const STUDENTS_ES5 = STUDENTS1.concat(STUDENTS2)
// es6写法
const STUDENTS_ES6 = [...STUDENTS1, ...STUDENTS2]
console.log('es5------',STUDENTS_ES5)
console.log('es6------',STUDENTS_ES6)
  1. 数组的克隆
const STUDENTS1 = ['小明','小芳','小红']
const PUPIL = [...STUDENTS1] // 注意:如果数组内元素是引用类型,拷贝的是内存地址,为浅拷贝
console.log('PUPIL----',PUPIL)
  1. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div')
console.log(divs) // 此处得到的divs实际是一个对象
const divsArr = [...divs] // 将其转为真正的数组,从而可以使用数组的api譬如filter、map
console.log(divsArr)

9.Symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第7种数据类型,是一个类似字符串的数据类型

Symbol特点

  1. Symbol的值是唯一的,用来解决命名冲突的问题
  2. Symbol值不能与其他数据进行运算,也不能与自己进行运算,譬如+、-、*、/、比较运算
  3. Symbol定义的对象属性不能使用for…in遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名

创建Symbol

  1. 通过let s2 = Symbol('张三') 的方式创建Symbol,'张三’作为Symbol描述,作用相当于注释,这种方式创建的Symbol,即使传入的描述一致,但实际返回的值是不同的
// 创建Symbol
let s = Symbol()
console.log(s,typeof s) // Symbol() "symbol"
let s2 = Symbol('张三') // '张三'作为Symbol描述,作用相当于注释
let s3 = Symbol('张三') // 即使传入的描述一致,但实际返回的值是不同的
console.log(s2 === s3) // false
  1. 通过Symbol.for()创建Symbol,这种方式创建Symbol,传入的描述一致,实际返回的值也一致,可以得到唯一的Symbol
// Symbol.for创建Symbol
let s4 = Symbol.for('张三')
let s5 = Symbol.for('张三')
console.log(s4 === s5) // true

Symbol使用场景

给对象添加属性和方法。由于Symbol值具有唯一性,所以可以很安全地把属性和方法加入对象中,如下所示

let game = {
    up: 'upp',
    down: 'doown'
}
let methods = {
    up: Symbol(),
    down: Symbol(),
}
// 添加方法
game[methods.up] = function(){
    console.log('up up up')
}
game[methods.down] = function(){
    console.log('down down down')
}
console.log('game----', game)
// 调用
game[methods.up]()
let youxi = {
    name: '狼人杀',
    [Symbol('say')]: function(){ // 此处不能直接写 Symbol('say'): function(){...},因为Symbol('say')是动态的,和上面固定的'name'不一样
        console.log('发言')
    }
}

Symbol内置值

ES6除了定义自己使用的Symbol值以外,还提供了11个内置的Symbol值,指向语言内部使用的方法,比如

  1. Symbol.hasInstance
    当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
 class Person{
        static [Symbol.hasInstance](param){
            console.log('param----', param)
            console.log('检测类型')
        }
    }
    let o = {}
    console.log(o instanceof Person)
    // param---- {}
    // 检测类型
    // false
  1. Symbol.isConcatSpreadable
    对象的Symbol.isConcatSpreadable属性等于一个bool值,表示该对象用于Array.prototype()时,是否可以展开
const arr1 = [1,2,3]
const arr2 = [4,5,6]
arr2[Symbol.isConcatSpreadable] = false // arr2不可展开
const arr = arr1.concat(arr2)
console.log(arr) // [1,2,3,[4,5,6]]

3.Symbol.unscopables

该对象指定了使用with关键字时,哪些属性会被with环境排除

4.Symbol.match

当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值

5.Symbol.replace

当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值

6.Symbol.search

当该对象被str.search(myObject)方法调用时,会返回该方法的返回值

7.Symbol.split

当该对象被str.split(myObject)方法调用时,会返回该方法的返回值

8.Symbol.iterator

对象进行for ... of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器

9.Symbol.toPrimitive

该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值

10.Symbol.toStringTag

在该对象上调用toString方法时,返回该方法的返回值

11.Symbol.species

创建衍生对象时,会使用该属性

相关文章
|
SQL 数据库
SQL面试50题------(初始化工作、建立表格)
这篇文章提供了SQL面试中可能会遇到的50道题目的建表和初始化数据的SQL脚本,包括学生、教师、课程和成绩表的创建及数据插入示例。
SQL面试50题------(初始化工作、建立表格)
|
编解码 JavaScript 前端开发
Vue项目实战(01)-vue-element-admin项目结构分析
Vue项目实战(01)-vue-element-admin项目结构分析
283 1
|
人工智能 自然语言处理 API
手把手教你搭建微信公众号AI助手
【8月更文挑战第6天】手把手教你搭建微信公众号AI助手
884 2
手把手教你搭建微信公众号AI助手
|
机器学习/深度学习 算法 调度
深度学习|改进两阶段鲁棒优化算法i-ccg
深度学习|改进两阶段鲁棒优化算法i-ccg
|
11月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
249 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
JavaScript 前端开发
vue配合axios连接express搭建的node服务器接口_简单案例
文章介绍了如何使用Express框架搭建一个简单的Node服务器,并使用Vue结合Axios进行前端开发和接口调用,同时讨论了开发过程中遇到的跨域问题及其解决方案。
206 0
vue配合axios连接express搭建的node服务器接口_简单案例
|
数据采集 存储 数据可视化
R语言时间序列分析:处理与建模时间序列数据的深度探索
【8月更文挑战第31天】R语言作为一款功能强大的数据分析工具,为处理时间序列数据提供了丰富的函数和包。从数据读取、预处理、建模到可视化,R语言都提供了灵活且强大的解决方案。然而,时间序列数据的处理和分析是一个复杂的过程,需要结合具体的应用场景和需求来选择合适的方法和模型。希望本文能为读者在R语言中进行时间序列分析提供一些有益的参考和启示。
|
JavaScript API
vue 异步网络请求 axios 【实用教程】(含访问本地接口)
vue 异步网络请求 axios 【实用教程】(含访问本地接口)
191 0
|
前端开发 API 数据库
Django(五):如何在Django中通过API提供数据库数据给前端
Django(五):如何在Django中通过API提供数据库数据给前端
384 9
|
存储 算法 Linux
【探索Linux】P.17(进程信号 —— 信号保存 | 阻塞信号 | sigprocmask() | sigpending() )
【探索Linux】P.17(进程信号 —— 信号保存 | 阻塞信号 | sigprocmask() | sigpending() )
230 0