ES6 常用函數(shù) 記一次分享內(nèi)容

ES6 新特性

簡(jiǎn)介:

  1. ECMAScript 6.0(以下簡(jiǎn)稱(chēng) ES6)是 JavaScript 新一代標(biāo)準(zhǔn),加入了很多新的功能和語(yǔ)法
  2. ECMAScript 和 JavaScript 的關(guān)系是:前者是后者的規(guī)格趴生,后者是前者的一種實(shí)現(xiàn)

var let const

var

1. ES5 中作用域有:全局作用域蝇刀、函數(shù)作用域甘萧。
// 全局作用域
var a = 123;
function test() {
  console.log(a);     
}
test();  // 123
//函數(shù)作用域
function test() {
  var a = 123;
}
test(); 
console.log(a);   // ReferenceError
// 不用var  全局定義
var z = 'n';
function test() {
  z = 'z';        
}
test(); 
console.log(z);     // z


var z = 'n';
function test() {
  var z = 'z';
}
test(); 
console.log(z);    // n
2. var聲明的變量會(huì)掛載在window上。容易引起變量污染。
// i只是用來(lái)控制循環(huán)晰韵, 但泄露為全局變量 
for (var i = 0; i < 3; i++) { }    
console.log(window.i);  // 3
3. 變量提升
var a = 123;
function test() {
  console.log(a);         // a在聲明前打印了  
  if(false) {           
    var a = 'abc';      // 變量提升,導(dǎo)致內(nèi)層的 a 變量覆蓋了外層的 a 變量
  }
}
test();  // undefined

let

ES6 中新增了塊級(jí)作用域概念链瓦。

1. 聲明的變量只在塊級(jí)作用域內(nèi)有效
 {  
   let i = 1;  
   { let i = 2; }      
 }  

if( ) { }

for( ) { }

2. 不存在變量提升(或者說(shuō)存在變量提升拆魏,但不賦值)盯桦,而是“綁定”在暫時(shí)性死區(qū)
var test = 1;
function func(){
  console.log(test);   
  let test = 2;     
};
func(); 
3. 不能重復(fù)聲明
{
   let a = 1;
   let a = 2;
}
// 報(bào)錯(cuò)

{
  let a = 10;
  var a = 1;
}
//報(bào)錯(cuò)

const

1. const一旦聲明變量,就必須立即初始化
const foo;  // 報(bào)錯(cuò)
2. 只在聲明所在的塊級(jí)作用域內(nèi)有效渤刃。
{
  const MAX = 5;
}
console.log(MAX)   //報(bào)錯(cuò)
3. 同樣存在暫時(shí)性死區(qū)拥峦,只能在聲明的位置后面使用。
{
  console.log(MAX); // 報(bào)錯(cuò)
  const MAX = 5;
}
4. 不能重復(fù)聲明卖子。
var message = 'Hello';
const message = 'Goodbye!';

let age = 25;
const age = 30;
5. const聲明一個(gè)簡(jiǎn)單數(shù)據(jù)類(lèi)型略号。一旦聲明,常量的值就不能改變洋闽。
const PI = 3.1415;
PI // 3.1415

PI = 3;  // 報(bào)錯(cuò)
6. const 定義的復(fù)合類(lèi)型的數(shù)據(jù)可以進(jìn)行修改:
const foo = { prop:1 };
foo.prop = 2;   // 只改了數(shù)據(jù)結(jié)構(gòu)玄柠,成功
foo = {};       // 改變了指針指向,報(bào)錯(cuò)
const a = [];
a.push('Hello');    // 不改動(dòng)指針指向诫舅,只改了數(shù)據(jù)結(jié)構(gòu)
a = ['lily'];      // 改變了指針指向羽利,報(bào)錯(cuò)
  • 對(duì)于簡(jiǎn)單類(lèi)型的數(shù)據(jù)(數(shù)值、字符串刊懈、布爾值)这弧,值就保存在變量指向的那個(gè)內(nèi)存地址,因此等同于常量虚汛,const不允許更改
  • 對(duì)于復(fù)合類(lèi)型的數(shù)據(jù)(主要是對(duì)象和數(shù)組)匾浪,變量指向的內(nèi)存地址,保存的只是一個(gè)指向?qū)嶋H數(shù)據(jù)的指針泽疆,const只能保證這個(gè)指針是固定的户矢,至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了

編程風(fēng)格

  1. 建議不再使用var命令殉疼,let命令取代梯浪。兩者語(yǔ)義相同,而且let沒(méi)有副作用(全局污染瓢娜,變量提升)
  2. 在let和const之間挂洛,建議優(yōu)先使用const,一是const比較符合函數(shù)式編程思想眠砾,我不改變值虏劲,只新建值。二是JavaScript 編譯器會(huì)對(duì)const進(jìn)行優(yōu)化褒颈,提高運(yùn)行效率
  3. const聲明常量還有兩個(gè)好處柒巫,一是閱讀代碼的人立刻會(huì)意識(shí)到不應(yīng)該修改這個(gè)值,二是萬(wàn)一修改了會(huì)報(bào)錯(cuò)
  4. 所有的函數(shù)都應(yīng)該設(shè)置為常量谷丸。

二堡掏、解構(gòu)賦值

  • 解構(gòu):ES6 允許按照一定模式,從數(shù)組和對(duì)象中提取值刨疼,對(duì)變量進(jìn)行賦值,
  • 可以叫做“模式匹配”泉唁,只要等號(hào)兩邊的模式相同鹅龄,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值。
1. 數(shù)組的解構(gòu)
let [a, b, c] = [1, 2, 3];  


// 不完全解構(gòu):
let [x, y] = [1, 2, 3]; 


// 嵌套數(shù)組進(jìn)行解構(gòu)
let [foo, [[bar], baz]] = [1, [[2], 3]]; 


// 只取第三個(gè)
let [ , , third] = ['foo', 'bar', 'baz']; 


// 中間的不取
let [x, , y] = [1, 2, 3];


// 取第一個(gè)  取剩余的 
let [head, ...other] = [1, 2, 3, 4];
head 
other  
 

let [...other, last] = [1, 2, 3, 4];  //  報(bào)錯(cuò):Rest element must be last element
2. 對(duì)象的解構(gòu)
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };

const { log, info, table, warn } = console; 
 
3. 解構(gòu)不成功系列:
let [foo] = [];   
// foo: undefined 

 
// 如果等號(hào)的右邊 是不可遍歷的結(jié)構(gòu)    
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {}; 
// 都將報(bào)錯(cuò)



// 不同名
let { abc } = { foo: 'aaa', bar: 'bbb' };
// abc: undefined
4. 用途:
// 交換變量的值  
let x = 1;
let y = 2; 
[x, y] = [y, x];


// 函數(shù) return 數(shù)組 對(duì)象  進(jìn)行解構(gòu)
function getArr() {
  return [1, 2, 3];
}
let [a, b, c] = getArr();


function getObj() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();
 

// 傳參:參數(shù)有次序的
function f([x, y, z]) { console.log(x,y,z) }
f([1, 2, 3]);

// 無(wú)序 也會(huì)對(duì)應(yīng)著解構(gòu)
function f({x, y, z}) { console.log(x,y,z) }
f({z: 3, y: 2, x: 1});
 

// 提取接口返回的 JSON 數(shù)據(jù)
const jsonData = {
  id: 42,
  status: 'OK',
  data: [867, 5309]
};
const { data } = jsonData;


import React, { Component } from 'react';
class SomeComponent extends Component { ... }
 

編程風(fēng)格

函數(shù)的參數(shù)如果是對(duì)象的成員亭畜,優(yōu)先使用解構(gòu)賦值扮休。

const user = {
    firstName:'firstName',
    lastName:'lastName'
}

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;
}

// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}

// best
function getFullName({ firstName, lastName }) { }

getFullName(user);

三、模板字符串

傳統(tǒng)的 JavaScript 語(yǔ)言拴鸵,輸出模板通常是這樣寫(xiě)的玷坠。

const basket = {
  count:123,
  onSale:20
}
 let str = 'There are ' + basket.count +  
  'items in your basket, ' +
  + basket.onSale +
  ' are on sale!';

上面這種寫(xiě)法相當(dāng)繁瑣不方便,ES6 引入了模板字符串解決這個(gè)問(wèn)題:

1. 反引號(hào)(`)標(biāo)識(shí) , 變量名寫(xiě)在 ${ } 之中劲藐。
const basket = {
  count:123,
  onSale:20
}
let str = `
  There are  ${basket.count}  items
   in your basket,  ${basket.onSale} 
  are on sale!
`
2. 進(jìn)行運(yùn)算
let obj = {x: 1, y: 2};

`${obj.x + obj.y}`
3. 調(diào)用函數(shù)
function fn() {
  return 'and';
}

`foo ${fn()} bar`

編程風(fēng)格

靜態(tài)字符串一律使用單引號(hào)或反引號(hào)侨糟,不使用雙引號(hào)。動(dòng)態(tài)字符串使用反引號(hào)瘩燥。

四秕重、函數(shù)的擴(kuò)展

1. 默認(rèn)值

ES6 之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值厉膀,只能采用變通的方法溶耘。 對(duì) 0 false不友好

function log(y) {
  y = y || '我是默認(rèn)值';
  console.log(y);
} 
log('傳值了');
log(0);       
log(false);

ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫(xiě)在參數(shù)定義的后面服鹅。

// 例子1:
function log(y = '我是默認(rèn)值') {
  console.log(y);
} 
log(0)
log(false)

// 例子2:
function Point(x = 0, y = 0) {
  this.x = x;
  this.y = y;
} 
const p = new Point();
p // { x: 0, y: 0 }
2. 函數(shù)的length屬性
  • length:該函數(shù)預(yù)期傳入的參數(shù)個(gè)數(shù)凳兵。
  • 指定了默認(rèn)值后,后面參數(shù)的length屬性將失真企软。
// 默認(rèn)值在不同位置的例子:

(function (a) {}).length  // 沒(méi)有默認(rèn)值

(function (a = 5) {}).length 

(function (a, b, c = 5) {}).length 

(function(...args) {}).length //  rest 參數(shù)   

(function (a = 0, b, c) {}).length 

(function (a, b = 1, c) {}).length 
3. rest 參數(shù)
// arguments 能通過(guò)下標(biāo)訪(fǎng)問(wèn) 轉(zhuǎn)成數(shù)組
function sortNumbers() {
  console.log(arguments)
  return Array.prototype.slice.call(arguments);
}
sortNumbers(1,2,3)

// rest參數(shù) 真正的數(shù)組
const sortNumbers = (...numbers) => {
  console.log(numbers)
}
sortNumbers(1,2,3)

4. 箭頭函數(shù)
  • ES6 允許使用“箭頭”(=>)定義函數(shù)庐扫。
let f = () => 5;
// 等同于
let f = function () { return 5 };



let sum = (num1, num2) => num1 + num2;
// 等同于
let sum = function(num1, num2) {
  return num1 + num2;
};


 
[1,2,3].map(function (x) {
  return x * x;
});
// 等同于 
[1,2,3].map(x => x * x);

 
  
const person = { 
  first:'first', 
  last:'last',
};
function full(person) {
  return person.first + ' and ' + person.last;
}
full(person)
// 等同于 
const full = ({ first, last }) => first + ' and ' + last; 
full(person)
  • 不能使用箭頭函數(shù)的情況
// 定義對(duì)象方法的時(shí)候 不能用箭頭函數(shù)
const cat = {
  lives: 9,
  jumps: () => {
    console.log(this);    // window
    this.lives--;     
  }
} 
cat.jumps();       // 箭頭函數(shù)只能調(diào)用外層的this  把函數(shù)上下文綁定到了 window 上

// 解決方案:
const dog = {
  lives: 9,
  jumps() {
    console.log(this === dog);    // 寫(xiě)成普通函數(shù) this就指向dog
    this.lives--;     
  }
} 
dog.jumps();




// 不可以當(dāng)作構(gòu)造函數(shù)。 因?yàn)闃?gòu)造函數(shù)需要有自己的this仗哨,箭頭函數(shù)沒(méi)有自己的this形庭,用的是外層的this
let X = () => {};
x = new X(); 


// 定義原型方法的時(shí)候 不能用箭頭函數(shù)
function Cat(name) {
    this.name = name;
} 
Cat.prototype.sayCatName = () => {
    console.log(this); //  window   箭頭函數(shù)調(diào)用外層的this
    return this.name;
}; 
const cat = new Cat('Mew');
cat.sayCatName();   // ''


// 定義事件回調(diào)函數(shù)  不能用箭頭函數(shù)
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
    console.log(this === window); // true
    this.innerHTML = 'Clicked button';
}); 

編程風(fēng)格

  • 使用匿名函數(shù)當(dāng)作參數(shù)的場(chǎng)合
// bad
[1, 2, 3].map(function (x) {
  return x * x;
}); 

// best
[1, 2, 3].map(x => x * x);
  • 箭頭函數(shù)取代Function.prototype.bind,不應(yīng)再用 self/_this/that 綁定 this厌漂。
// bad
const self = this;
const boundMethod = function(...params) {
  return method.apply(self, params);
} 

// best
const boundMethod = (...params) => method.apply(this, params);
  • 不要在函數(shù)體內(nèi)使用 arguments 變量萨醒,使用 rest 運(yùn)算符(...)代替。
// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('');
}

// good
function concatenateAll(...args) {
  return args.join('');
}
  • 函數(shù)默認(rèn)值
// bad
function handleThings(opts) {
  opts = opts || {};
}

// good
function handleThings(opts = {}) {
  // ...
}

五苇倡、數(shù)組的擴(kuò)展

1.擴(kuò)展運(yùn)算符
console.log(...[1, 2, 3])


console.log(1, ...[2, 3, 4], 5)


[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]


// 合并數(shù)組
function push(array, ...items) {
  array.push(...items);
  return array;
}
push([1,2,3]4,5,6)


// 函數(shù)參數(shù)展開(kāi)
const arr = [0, 1, 2];
function f(x, y, z) { 
  console.log(x,y,z)
}
f(...arr);


// 合并數(shù)組
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e']; 
// ES5 
arr1.concat(arr2, arr3);  
// ES6 
[...arr1, ...arr2, ...arr3] 


//拆分字符串
[...'hello']
// [ 'h', 'e', 'l', 'l', 'o' ]


// 遍歷map類(lèi)型的keys
let map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]); 
[...map.keys()]
[...map.values()]


// Generator 返回?cái)?shù)組
const go = function*(){
  yield 1;
  yield 2;
  yield 3;
}; 
[...go()]    // [1, 2, 3] 
2. Array.from()
  • 將對(duì)象轉(zhuǎn)為真正的數(shù)組
  • 偽數(shù)組:
    • arguments對(duì)象
    • document.querSelectAll('div') 返回的對(duì)象
    • 字符串
// 偽數(shù)組的轉(zhuǎn)換
let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3,
}; 
console.log(arrayLike instanceof Array)  // false;
let arr1 = [].slice.call(arrayLike);    // ES5  轉(zhuǎn)換成數(shù)組
let arr2 = Array.from(arrayLike);    // ES6  轉(zhuǎn)換成數(shù)組


// arguments對(duì)象
function foo() {
  let args = Array.from(arguments); 
  console.log(arguments instanceof Array)  
  console.log(args instanceof Array)
}
foo(1,2,3); 
 

// 字符串
Array.from('string'); 
  • Array.from 第二個(gè)參數(shù)富纸,作用類(lèi)似于數(shù)組的map方法
let arr = [2,3,4];

Array.from(arr, x => x * x);
// 等同于
Array.from(arr).map(x => x * x);
3. 數(shù)組實(shí)例的 includes()
// ES5 判讀是否存在與數(shù)組 
[1,2,3,NaN].indexOf(1) !== -1 ? console.log('存在') : console.log('不存在');
[1,2,3,NaN].indexOf(4) !== -1 ? console.log('存在') : console.log('不存在');
 //  誤判  缺點(diǎn):1. 不夠語(yǔ)義化 2. 它內(nèi)部使用嚴(yán)格相等運(yùn)算符(===)進(jìn)行判斷 
[1,2,3,NaN].indexOf(NaN) !== -1 ? console.log('存在') : console.log('不存在');   
  

// ES6:  
[1, 2, 3].includes(1)     // true
[1, 2, 3].includes(4)     // false
[1, 2, 3, NaN].includes(NaN) // true

六.對(duì)象的擴(kuò)展

1. Object.assign()
  • 對(duì)象的合并
const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}    
  • 自動(dòng)轉(zhuǎn)換成對(duì)象
typeof Object.assign(2)   // 'object'     
Object.assign(undefined) // 報(bào)錯(cuò)  
Object.assign(null)   // 報(bào)錯(cuò)  undefined和null無(wú)法轉(zhuǎn)成對(duì)象
  • 屬于淺拷貝 或者說(shuō)是一級(jí)深拷貝
const obj1 = { 
  a: { b: 1 },
  c:2
};
const obj2 = Object.assign({}, obj1);   // 與 {} 拼接會(huì)產(chǎn)生一個(gè)新的對(duì)象

obj1.c = 3;   
obj2     // c不會(huì)變  一級(jí)深拷貝

obj1.a.b = 2;   
obj2      // b會(huì)跟著變 并沒(méi)有開(kāi)辟新地址
  • 數(shù)組的處理
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
  • 用途:
// ES5寫(xiě)法  prototype 添加方法
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};
// ES6 prototype 添加方法
Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});
2. Object.keys(),Object.values()旨椒,Object.entries()
  • 拿對(duì)象的keys values 鍵值對(duì)
let obj1 = { foo: 'bar', baz: 42 };
Object.keys(obj1)

let obj2 = { foo: 'bar', baz: 42 };
Object.values(obj2)

let obj3 = { foo: 'bar', baz: 42 };
Object.entries(obj3)
  • 與for of結(jié)合
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };

// 拿obj的keys
for (let key of keys(obj)) {
  console.log(key);  
}

// 拿obj的values
for (let value of values(obj)) {
  console.log(value);  
}

for (let [key, value] of entries(obj)) {
  console.log(key, value); 
}
3. Object.fromEntries()
  • Object.entries()的逆操作晓褪,用于將一個(gè)鍵值對(duì)數(shù)組轉(zhuǎn)為對(duì)象。
Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: 'bar', baz: 42 }

七. Promise

1. 簡(jiǎn)介
  • Promise 是異步編程的一種解決方案

  • 有三種狀態(tài):pending(進(jìn)行中)综慎、fulfilled(已成功)和rejected(已失敾练隆)。 只有異步操作的結(jié)果寥粹,可以決定當(dāng)前是哪一種狀態(tài)变过。

  • 缺點(diǎn):
    無(wú)法取消Promise,一旦新建它就會(huì)立即執(zhí)行涝涤,無(wú)法中途取消媚狰。
    其次,如果不設(shè)置回調(diào)函數(shù)阔拳,Promise內(nèi)部拋出的錯(cuò)誤崭孤,不會(huì)反應(yīng)到外部。
    第三糊肠,當(dāng)處于pending狀態(tài)時(shí)辨宠,無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)。

  • Promise對(duì)象是一個(gè)構(gòu)造函數(shù)货裹,創(chuàng)造Promise實(shí)例

  • resolve: “未完成”變?yōu)椤俺晒Α?/p>

  • reject: “未完成”變?yōu)椤笆 ?/p>

  • 一般來(lái)說(shuō)嗤形,調(diào)用resolve或reject以后,Promise 的使命就完成了弧圆,后繼操作應(yīng)該放到then方法里面赋兵,而不應(yīng)該直接寫(xiě)在resolve或reject的后面。

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    return resolve(value);
  } else {
    return reject(error);
  }
}); 
2. then()
  • 第一個(gè)回調(diào)函數(shù) 狀態(tài)變?yōu)閞esolved時(shí)調(diào)用
  • 第二個(gè)回調(diào)函數(shù) 狀態(tài)變?yōu)閞ejected時(shí)調(diào)用
promise.then(function(value) {
  // success  resolved時(shí)調(diào)用
}, function(error) {
  // failure  rejected時(shí)調(diào)用 
});

拿ajax舉例:

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open('GET', url);
    client.onreadystatechange = handler;
    client.responseType = 'json';
    client.setRequestHeader('Accept', 'application/json');
    client.send();

  });

  return promise;
};

// 一個(gè)異步
getJSON('/posts.json').then(
   json => console.log(json),
   err => console.error('出錯(cuò)了', err)
);

// 嵌套異步
getJSON('/post/1.json').then(
  post => getJSON(post.commentURL)      // 返回的還是一個(gè)Promise對(duì)象(即有異步操作)
).then(
  comments => console.log('resolved: ', comments),   // 等待前一個(gè)Promise對(duì)象的狀態(tài)發(fā)生變化搔预,才會(huì)被調(diào)
  err => console.log('rejected: ', err)
); 
3. catch()
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good     可以捕獲then執(zhí)行中的錯(cuò)誤霹期,也更接近同步的寫(xiě)法(try/catch)
promise 
  .then(function(data) { 
    // success      
  })
  .catch(function(err) {
    // error
  });
4. Promise.all()
  • 6 個(gè) Promise 實(shí)例, 6個(gè)都成功或1個(gè)失敗 才會(huì)走回調(diào)
  • 6個(gè)都成功:返回值組成一個(gè)數(shù)組給回調(diào)
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + '.json');
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

八. Iterator(遍歷器)

  • 遍歷器(Iterator):是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪(fǎng)問(wèn)機(jī)制拯田。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口历造,就可以完成遍歷操作
  • ES6新增:Map Set 結(jié)構(gòu)
let m = new Map();
m.set('numberA', 67);
m.set('numberB', 88);
m.get('numberA');   

let s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
  • ES6 新增遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi), Set 和 Map 結(jié)構(gòu)船庇、arguments對(duì)象吭产、DOM NodeList 對(duì)象、Generator 對(duì)象鸭轮,以及字符串垮刹。

  • 任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口

let iterable = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
  console.log(item); // 'a', 'b', 'c'
}
  • 原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu):
    Array, Map, Set, String, 函數(shù)的arguments對(duì)象, NodeList對(duì)象
// Array
const arr = ['red', 'green', 'blue'];
for(let v of arr) {
  console.log(v); // red green blue
}


// Set
const engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}

let generator = function* () {
  yield 1;
  yield 2;
  yield 5;
};

var iterator = generator();

for(let v of iterator) {
  console.log(v);  
}

九. Generator

1. 簡(jiǎn)介
  • Generator 也是異步編程的一種解決方案
  • function關(guān)鍵字與函數(shù)名之間有一個(gè)星號(hào)
  • 函數(shù)體內(nèi)部使用yield表達(dá)式,暫停執(zhí)行的標(biāo)記
  • Generator函數(shù)并不執(zhí)行张弛,返回的也不是函數(shù)運(yùn)行結(jié)果荒典,而是一個(gè)指向內(nèi)部狀態(tài)的指針對(duì)象,我們可以通過(guò)調(diào)用 next 方法吞鸭,使得指針移向下一個(gè)狀態(tài)
2.語(yǔ)法
  • *的位置
function * foo(x, y) { ··· }
function *foo(x, y) { ··· }
function* foo(x, y) { ··· }
function*foo(x, y) { ··· }


let obj = {
  * myGeneratorMethod() {
    ···
  }
};
// 等價(jià)
let obj = {
  myGeneratorMethod: function* () {
    // ···
  }
};
  • 在另一個(gè)表達(dá)式之中寺董,必須放在圓括號(hào)里面。
  • 函數(shù)參數(shù)或放在賦值表達(dá)式的右邊刻剥,可以不加括號(hào)遮咖。
function* demo() {
  console.log('Hello' + yield);        // SyntaxError
  console.log('Hello' + yield 123);    // SyntaxError

  console.log('Hello' + (yield));      // OK
  console.log('Hello' + (yield 123));  // OK

  foo(yield 'a', yield 'b');    // OK
  let input = yield;           // OK
}
3. 方法屬性
  • yield:暫停
  • next:執(zhí)行
  • value:是yield表達(dá)式的值
  • done:表示遍歷是否結(jié)束。
function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
//'   { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }
3. next()
  • next的參數(shù):設(shè)置成上一個(gè)yield表達(dá)式的返回值
  • next的輸出:會(huì)執(zhí)行一條yield語(yǔ)句造虏,并返回yield后面的值
function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
} 

let b = foo(5);
b.next() // { value:6, done:false }    x=5御吞, 執(zhí)行第一行麦箍,輸出yield的值    x+1的值6 
b.next(12) // { value:8, done:false }  y=24,執(zhí)行第二行陶珠,輸出yield的值 將上一次yield表達(dá)式的值設(shè)為12   24/3=8
b.next(13) // { value:42, done:true }  z=13  執(zhí)行第三行挟裂, return (x + y + z);
4. throw()、return()

function* gen(x,y){
  yield 1;
  yield 2;
  yield 3;
}
let g = gen();
g.next();    //{value: 1, done: false}
g.return(5); //{value: 5, done: true}
g.next();    //{value: undefined, done: true} 

 
function* foo(x,y){
  yield 1;
  yield 2;
  yield 3;
}
let f = foo();
f.next();    //{value: 1, done: false}
f.throw(new Error('出錯(cuò)了'));    // Error
f.next();    //{value: undefined, done: true} 


5. 異步對(duì)比
// 傳統(tǒng)回調(diào)函數(shù)
ajax('url_1', () => {
    // callback 函數(shù)體
    ajax('url_2', () => {
        // callback 函數(shù)體
        ajax('url_3', () => {
            // callback 函數(shù)體
        })
    })
})

// 無(wú)法取消 Promise 揍诽,錯(cuò)誤需要通過(guò)回調(diào)函數(shù)來(lái)捕獲
ajax('url_1')
  .then(res => {
      // 操作邏輯
      return ajax('url_2')
  }).then(res => {
      // 操作邏輯
      return ajax('url_3')
  }).then(res => {
      // 操作邏輯
  })

// Generator
function *fetch() {
    yield ajax('XXX1', () => {})
    yield ajax('XXX2', () => {})
    yield ajax('XXX3', () => {})
}
let it = fetch()
let result1 = it.next()
let result2 = it.next()
let result3 = it.next()

// async/await
async function test() {  
  let result1 = await fetch('XXX1')
  let result2 = await fetch('XXX2')
  let result3 = await fetch('XXX3')
}

十. class

1. 構(gòu)造函數(shù) 與 class
//ES5 生成實(shí)例對(duì)象的傳統(tǒng)方法
function Point(x, y) {
  this.x = x;
  this.y = y;
} 
Point.prototype.toString = function () {
  return `${this.x},${this.y}`
}; 
let p = new Point(1, 2);

// ES6  class
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  } 
  toString() {
    return  `${this.x},${this.y}`
  }
}

//其實(shí)就是調(diào)用原型上的方法诀蓉。
// 等同于   
Point.prototype = { 
  constructor() {},
  toString() {}
};
2. new類(lèi)的實(shí)例
  • 定義在this上的屬性才是屬于實(shí)例的本身,否則都是定義在其原型上
  • x,y綁定在point上暑脆,toString綁定在Point上
//定義類(lèi)
class Point { 
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.toString = this.toString.bind(this);
  }
 
  toString() {  // 普通函數(shù)需綁定this
    return `${this.x},${this.y}`
  } 

  //toString = () => {  // 箭頭函數(shù)不需要綁定this 引用外層this
  //  return `${this.x},${this.y}`
  //} 
}

let point = new Point(2, 3); 
let { toString } = point;
toString();  // (2, 3)

// 檢測(cè)自身屬性中是否具有指定的屬性
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true

point.hasOwnProperty('toString') // false
point.__proto__.constructor === Point;  // true
point.__proto__.hasOwnProperty('toString') // true   方法在point的原型Point上
3. 繼承
  • ES5繼承:通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性, 通過(guò)原型鏈來(lái)繼承方法
  • 先創(chuàng)造子類(lèi)的實(shí)例對(duì)象this渠啤,然后再將父類(lèi)的方法屬性用call方法添加到this上面 。
function Father(name, age){
    this.name = name;
    this.age = age;
} 

function Son(name, age){
    Father.call(this, name, age);
}

Son.prototype = Object.create(Father.prototype);  // 通過(guò)Object.crete()去關(guān)聯(lián)兩者的prototype
Son.prototype.constructor = Son;                  // 將 Son 的constructor指向自己
Son.prototype.show = function () {
    console.log(this.name,this.age);
};
var s = new Son('子類(lèi)', 110);  
s.show();
  • ES6繼承
// class構(gòu)造一個(gè)父類(lèi)
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  p() {
    return 2;
  }
}

// extends,super關(guān)鍵字  繼承所有的屬性添吗,方法
class ColorPoint extends Point {   // 先生成父類(lèi)實(shí)例
  constructor(x, y) {         // 調(diào)用子類(lèi)的構(gòu)造函數(shù)修飾父類(lèi)實(shí)例
    super(x, y);              // super當(dāng)函數(shù)用   
    console.log(x,y);         
    console.log(super.p());   //  super當(dāng)對(duì)象用
  }
}
 
let colorPoint = new ColorPoint('xx','yy');

// 如何判斷一個(gè)類(lèi)是否繼承了另一個(gè)類(lèi) 
Object.getPrototypeOf(ColorPoint) === Point;



結(jié)束!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沥曹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碟联,更是在濱河造成了極大的恐慌架专,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玄帕,死亡現(xiàn)場(chǎng)離奇詭異部脚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)裤纹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)委刘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鹰椒,你說(shuō)我怎么就攤上這事锡移。” “怎么了漆际?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵淆珊,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我奸汇,道長(zhǎng)施符,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任擂找,我火速辦了婚禮戳吝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贯涎。我一直安慰自己听哭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著陆盘,像睡著了一般普筹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隘马,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天太防,我揣著相機(jī)與錄音,去河邊找鬼祟霍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛盈包,可吹牛的內(nèi)容都是我干的沸呐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼呢燥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崭添!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起叛氨,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤呼渣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后寞埠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體屁置,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年仁连,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蓝角。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饭冬,死狀恐怖使鹅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昌抠,我是刑警寧澤患朱,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炊苫,受9級(jí)特大地震影響裁厅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侨艾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一姐直、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒋畜,春花似錦声畏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愿棋。三九已至,卻和暖如春均牢,著一層夾襖步出監(jiān)牢的瞬間糠雨,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工徘跪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甘邀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓垮庐,卻偏偏與公主長(zhǎng)得像松邪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哨查,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 第一章:塊級(jí)作用域綁定 塊級(jí)聲明 1.var聲明及變量提升機(jī)制:在函數(shù)作用域或者全局作用域中通過(guò)關(guān)鍵字var聲明的...
    BeADre_wang閱讀 839評(píng)論 0 0
  • [TOC] 參考阮一峰的ECMAScript 6 入門(mén)參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,781評(píng)論 0 1
  • 本文為阮一峰大神的《ECMAScript 6 入門(mén)》的個(gè)人版提純逗抑! babel babel負(fù)責(zé)將JS高級(jí)語(yǔ)法轉(zhuǎn)義,...
    Devildi已被占用閱讀 1,985評(píng)論 0 4
  • let ES6新增的用于變量聲明的關(guān)鍵字 通過(guò)let聲明的變量寒亥,不允許重復(fù)聲明 不支持變量聲明預(yù)解析邮府,let變量,...
    年過(guò)古稀的Coder閱讀 296評(píng)論 0 1
  • 轉(zhuǎn)載請(qǐng)注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c...
    深沉的簡(jiǎn)單閱讀 1,859評(píng)論 0 40