es6 新特性

1、let、const 声明变量

  • var 是容许从新赋值、从新定义的,只有 global 和 function scope 做用域,在 if 内无做用域git

  • letconst 拥有 block scope 做用域,有 {} 的时候就代表它的做用域范围github

  • letconst 不可重复声明一个变量,因此使用 var 容易不当心覆盖原来的变量web

  • let 能够从新赋值,const 不能够从新赋值ajax

  • const 也是能够修改的,不过要是引用类型,至关于人(Person)是不可改变的,但个人年龄会随着时间改变数组

const person = { name: 'Jelly', age: 20 } person.age = 21;

实在不但愿改变,能够经过 Object.freezemarkdown

阻止修改现有属性的特性和值,并阻止添加新属性。app

const person = { name: 'Jelly', age: 20 } const Jelly = Object.freeze(person); person.age = 21; // 没法修改,返回值依旧是 20

应用场景

一、经过 letconst 实现私有变量函数

window 对象下有一个 name 属性ui

window.name = 'Jelly'; // 这样就影响到 window 下的 name 属性

为了保证咱们不影响到 window 下的 name 属性,咱们经过 IIFE(当即执行函数)去实现私有化变量,但为了这个目的而去写这个函数,不利于代码的可读性this

(function() {
  var name = 'Jelly'; })(); window.name // ""

有了 letconst 就能够经过它们的特性 block scope 来实现了

{
  const name = 'Jelly'; } window.name // ""

二、for 循环应用场景

for (var i = 0; i < 10; i++) { // 每次循环都重写了 i 的值 setTimeout(function() { // 模拟 ajax 请求 console.log(`i:${i}`); // i:10(10个重复) }, 1000); } console.log(window.i); // 10

上面返回 10个 i:10 的缘由就在于,在 setTimeout 1秒后执行的时候,循环已经结束

只需将 var 改成 let 声明,每次声明的都属于当前的块级做用域,setTimeout 只认这个做用域

for (var i = 0; i < 10; i++) { // 每次循环都重写了 i 的值 setTimeout(function() { // 模拟 ajax 请求 console.log(`i:${i}`); // 输出 i:0 到 i:9 }, 1000); } console.log(window.i); // 10

PS:const 不能使用,const 的值是不能从新赋值的

三、临时性死区(Temporal dead zone)

console.log(color); var color = 'yellow'; console.log(color); // undefined

缘由是变量提高(是 JS 将声明移到做用域的顶部)

至关因而:

var color;
console.log(color); color = 'yellow';

使用 letconst 呢?

console.log(color); // ReferenceError let color = 'yellow';

一样有变量提高,它们会存在于临时性死区,因此这个特征让咱们养成在变量未声明的时候,不要使用

2、箭头函数(arrow function)

三个特色:

  • 简明的语法
  • 隐式返回
  • 不绑定 this

简明的语法

// 传统写法 const numbers = [5, 6, 13, 5]; const double = numbers.map(function(number) { return number * 2; }) console.log(double); 
// 简化 const numbers = [5, 6, 13, 5]; const double = numbers.map(number => { // 一个参数不须要括号,多个参数须要,没有参数须要保留括号 return number * 2; }) console.log(double); 

隐式返回

有 return 则表示是显示返回

const numbers = [5, 6, 13, 5]; const double = numbers.map(number => number * 2); // 放在一行,在咱们须要简单返回一个东西的时候特别有用 console.log(double); 

不绑定 this

const Jelly = { name: 'Jelly', hobbies: ['Coding', 'Reading', 'Sleeping'], printHobbies: function() { console.log(this); // printHobbies 的 this 指向调用它的对象 Jelly this.hobbies.map(function(hobby) { // map 函数是独立的函数,独立运行时候,没经过 call、apply、bind 来改变 this 的状况下,这个 this 则指向 window、global 或者在严格模式下指向 undefined console.log(`${this.name} loves ${hobby}`); }); } } Jelly.printHobbies(); // 打印不对,this.name 是空

老方法是经过:var self = this

新方法则经过箭头函数,箭头没有本身的 thisthis 是继承父级的

this.hobbies.map(hobby => { console.log(`${this.name} loves ${hobby}`); });

箭头函数都是匿名函数(如何使用命名函数的箭头函数)

首先了解什么是命名函数:

function greet(name) { // 在递归和解除绑定的时候特别有用 console.log(`Hello ${name}`); } greet('lth'); // Hello lth

箭头函数要写成命名函数可:

let greet = name => {console.log(`Hello ${name}`)}; greet('lth'); // Hello lth

应用场景

一、做为构造函数,一个方法须要绑定到对象

const Person = (name, points) => { this.name = name; // 这里用了箭头函数,this 并无绑定到 Jelly 这个对象上去 this.points = points; } const Jelly = new Person('jelly', 5); // new Person 会完成四个步骤: // 生成一个新的对象、把构造函数中的 this 值指向这个新生成的对象、把这个绑定到它的原型对象、返回这个新生成的对象 Person.prototype.updatePoints = () => { this.points++; // 这里的 this 指向 window,因此要使用正常的 function,这样才能绑定到对象上去 console.log(this.points) } // 以上代码会报错 const Person = function(name, points) { this.name = name; this.points = points; } const Jelly = new Person('jelly', 5); Person.prototype.updatePoints = function() { this.points++; console.log(this.points) } Jelly // object name: 'jelly', points: 5 Jelly.updatePoints(); // 6

二、当你真的须要 this 时

const button = document.querySelector('.zoom'); button.addEventListener('click', () => { this.classList.add('in'); // 找不到绑定的对象 button,此时的 this 指向 window setTimeout(() => { this.classList.remove('in'); }, 2000) }) const button = document.querySelector('.zoom'); button.addEventListener('click', function() { this.classList.add('in'); setTimeout(() => { this.classList.remove('in'); }, 2000) })

三、须要使用 arguments 对象

// 这个功能返回全部参数的和 const sum = () => { return Array.from(arguments) // 在箭头函数中是没有 arguments 这个对象的 .reduce((prevSum, value) => prevSum + value, 0) } const sum = function() { return Array.from(arguments) // 这个 from 是将类数组对象转化为真正的数组对象 .reduce((prevSum, value) => prevSum + value, 0) }

3、参数默认值

// 老方法 function userInfo(a, b) { a = a || 5; // 参数默认声明,不须要从新声明 b = b || 6; return a * b; }
// ES6 新方法 function userInfo(a = 5, b = 6) { // 提升可读性 return a * b; } userInfo(); // 30 userInfo(4); // 24 userInfo(undefined, 5); // 25 不是第一个值的时候,传 undefined

4、模版字符串

字符串拼接能够简化,不用各类 ++++++ 了

const person = 'Jelly'; const age = 5; const sentence = `${person} is ${age} years old.`;
// 老方法 const template = [ '<div class="greet">', '<p>Hello</p>', '</div>' ].join(''); console.log(template);
// 新方法,模版字符串会保留空格 const template = `  <div class="greet">  <p>Hello</p>  </div> `.trim(); console.log(template);

应用场景

一、经过模版字符串输出列表

const Jelly = { name: 'jelly', date: '2017-05-07', todos: [ { name: 'Go to Store', completed: false }, { name: 'Watch Movie', completed: true }, { name: 'Running', completed: true } ] } const template = `  <ul>  ${Jelly.todos.map(todo => `  <li>  ${todo.name} ${todo.completed ? '✅' : '❌'}  </li>  `).join('')}  </ul> ` document.body.innerHTML = template;

二、给传入的参数加标签

function highlight(strings, ...values) { // strings 是个数组表示中间的字符串,values 表示 ${} 那些值 // debugger; // 这样能够看到 highlight 的组成 const highlighted = values.map(value => `<span class="highlight">${value}</span>`); let str = ''; strings.forEach((string, i) => str += `${string}${highlighted[i] || ''}`); return str; // 上面的 for return 也能够用 reduce 来处理 // return strings.reduce((prev, curr, i) => `${prev}${cur}${highlighted[i] || ''}`, ''); } const user = 'Mary'; const topic = 'Learn to use markdown'; const sentence = highlight`${user} has commented on your topic ${topic}`;

三、过滤用户输入

防止用户在输入框的内容中,插入非法字符串或脚原本实现 XSS (跨站脚本攻击),她们能够从在实现获取 Cookie、Session、密码之类的敏感信息

使用到的库:DOMPurify.js

下面这个案例就过滤掉了内嵌的 onload 事件

function sanitize(strings, ...values) { const dirty = strings.reduce((prev, curr, i) => `${prev}${curr}${values[i] || ''}`, ''); return DOMPurify.sanitize(dirty); } addCommentForm.addEventListener('submit', function(event) { event.preventDefault(); const newComment = textarea.value.trim(); if (newComment) { CommentDiv.innerHTML = sanitize`  <div class="comment-header">${user}</div>  <div class="comment-body">${textarea.value}</div>  ` textarea.value = ''; } });

5、字符串新增方法

  • .startsWith()
  • .endsWidth()
  • .includes()
  • .repeat()
const id = '51030019800730366x'; const fan = 'I love Laravist'; id.startsWith('51'); // true // 是否是以 51 开头的 id.startsWith('1980', 6); // true // 第 6 位开始是否是以 1980 开头的 // 区分大小写 fan.startsWith('I'); // true fan.startsWith('i'); // false id.endsWith('x'); // true id.endsWith('X'); // false fan.endsWith('love', 6); // true // 在 includes 方法以前咱们用 indexOf fan.indexOf('Laravist') !== -1 // true fan.includes('Laravist') // true fan.includes('Laravist', 10) // false 第十位开始有没有 Laravist '哈'.repeat(10)

应用场景

一、实现右对齐

function padder(string, length = 25) { return `${' '.repeat(Math.max(length - string.length), 0)}${string}` }

6、对象解构

const Tom = { name: 'Tom Jones', age: 25, family: { mother: '123', father: '456', brother: '789' } } const name = ''; // 会报错! const { name, age } = Tom; // 先声明,而后去 Tom 对象找同名的属性 console.log(name); // 'Tom Jones' console.log(age); // 25 // 若是你想本身声明的话,用一堆括号包裹 let name = ''; ({ name, age } = Tom); // 会解析成代码块,而不是对象解构的语法 console.log(name); console.log(age); // 要访问 family 也能够这么写 const { fater, mother, brother } = Tom.family;

对象解构重命名

// 若是 father 已经别人提早声明了 const { father: f, mother, brother } = Tom.family; // 讲 father 重命名为 f,但要注意的是,并无声明 father,而是声明了 f,而后去 Tom.family 里找 father 属性 console.log(f); // 123 console.log(father); // not defined console.log(sister); // undefined

对象解构默认值

// 可设置默认值,属性值要是 undefined 的时候 const { father: f, mother, brother, sister = 'have no sister' } = Tom.family; console.log(sister); // have no sister

经常使用于一些库,会提供一个 options 的选项让你来自定义属性,它们会有默认值

function appendChildDiv(options = {}) { const { parent = 'body', width = '100px', height = '80px', backgroundColor = 'pink' } = options; const div = document.createElement('div'); div.style.width = width; div.style.height = height; div.style.backgroundColor = backgroundColor; document.querySelector(parent).appendChild(div); } appendChildDiv({ parent: '.container', width: '200px', height: '150px', backgroundColor: 'blue' })

7、数组解构

const numbers = ['one', 'two', 'three', 'four']; const [one, two] = numbers; console.log(one, two); // one two // 想获取 一、3 const [one, ,three] = numbers; console.log(one, three); // one three // 获取全部 const [one, ...others] = numbers; // ...other 只能存在于最后一个,不能是 const [one, ...others, five] = numbers; console.log(one, others); // one ['two', 'three', 'four']

数组解构默认值

const details = ['JellyBool', 'laravist.com']; const [name, website, category = 'PHP'] = details; // 默认值为 undefined 时才生效 console.log(name, website, category); // JellyBool laravist.com PHP

应用场景

一、交换变量

// 老办法 let a = 10; let b = 20; let temp; temp = a; a = b; b = temp; // 新办法 [a, b] = [b, a]

8、for-of 遍历

传统的有三种方法:for、forEach、for-in

for 在于繁琐
forEach 缺点在于:不能停止 break、continue、return
for in 在于会遍历全部可枚举的属性
for-of 如今暂时不支持对象

// for-in 须要注意的是,遍历对象上可枚举的属性 friuts.describe = 'My favorite fruits'; // 或者给原型加一个方法 friuts.prototype.first = function() { return this[0]; } // 新增的属性和方法都会被遍历出来

for-of 的使用

// 只需将 for in 改成 for of 便可 for (let fruit of fruits) { // 要用 let if (fruit === 'Orange') { // 可停止 break; } console.log(fruit) }

应用场景

一、可用于可迭代对象

对象有内置了遍历器接口

fruits.entries() // 会返回 Array Iterator{} // 这个就是它的遍历接口
const fruits = ['Apple', 'Banana', 'Orange', 'Mango']; for (let [index, fruit] of fruits.entries()) { console.log(`${fruit} ranks ${index + 1} in my favorite fruits`); } // Apple ranks 1 in my favorite fruits // Banana ranks 2 in my favorite fruits // Orange ranks 3 in my favorite fruits // Mango ranks 4 in my favorite fruits

二、转换类数组 arguments

function sum() { let total = 0; for (let num of arguments) { total += num; } return total; } sum(1,2,3,4,5,6,7,8,9,10); // 55

三、绑定事件

const lis = document.querySelector('li'); for (let li of lis) { li.addEventListener('click', function() { this.classList.toggle('completed'); }) }
相关文章
相关标签/搜索