20181210-es6(let&const&解構&模版字串原理 &展開運算子、剩餘運算子運用 & 深拷貝原理 & reduce原理 & 箭頭函式)

。同學發表於2018-12-11

變數宣告

var 特點:
1.可以重複宣告
2.不能定義常量
3.不支援塊級作用域
複製程式碼
  • let
//1.不存在預解釋 變數提升
//2.暫時性死區
//3.具備塊級,同一塊內不能重複宣告;
 let a ={name:'xiaoming'}
 if(true){
     let a = 'xiaohong'//不同塊,可以宣告相同名;
 }
 console.log(a) //{name:'xiaoming'}
 
 if(true){
     let v= '20130401'
 }
 console.log(v)   //報錯:v is not defined
 
 for(var i=0;i<3;i++){//i是全域性的
 //閉包
     (function(i){
         setTimeout(function(){
             console.log(i)
         })
     })(i)
 }
 //用let
 for(let i = 0;i<3;i++){//i是塊級的
     setTimeout(function(){
         console.log(i)
     },1000)
 }
複製程式碼
  • const
//不存在預解釋、變數提升
//不能重複定義宣告
//不能更改他的值。
//具備塊級

const str = 123;
str = 3445;//報錯:常量不能重新賦值

const = obj = {name:'xiaoming'}
obj.name= 'xiaohong'//可以修改;const限制的是不能給變數重新賦值,給變數的屬性修改,實際並未修改記憶體地址。

複製程式碼

解構

解構就是分解一個物件的解構,可以用一種類似陣列的方式定義n個變數,可以將一個陣列中的值按照規則賦值過去。
解構的時候,等號兩邊結構類似;左邊物件右邊就是物件;左邊資料右邊也得是陣列,右邊還必須是一個真是存在的值;
複製程式碼
  • 陣列、物件的簡單解構賦值
var arr = [1,2,3]
var [a,b,c] = arr; // a=>1 b=>2 c=>3

var obj = {a:1,b:2}
var {a,b} = obj; //物件解構,根據key解構,a=>1,b=>2 
var {a:a1,b:b1} = obj;// 物件解構,不用key作為變數名,指定變數名;  a1=>1  b1=>2
複製程式碼
  • 巢狀解構賦值
var arr = [{a:1,b:2},[3,4],5]
var [{a,b},[c,d],e] = arr; //結構一樣,a=1 b=2,c=3,d=4,e=5

var [obj,ary,n] = arr ; //整合起來賦值,obj= {a:1,b:2} ary=[3,4] n=5

複製程式碼
  • 預設賦值解構;如果能取到值就用取到的,取不到(undefined)時就用預設的值;
var obj = {a:1}
var {a,b} = obj;
console.log(b)//undefined
var {a,b=2} = obj;
console.log(b)//2

var ary = [1,,3]//ary[1] = undefined
var [a = "a", b = "b", c =new Error('C必須指定')] = ary;
console.log(a, b, c);// 1,b,3



function ajax(options){
    var method = options.method || 'get'
    var data = options.data || {}
    ...
    
}
函式宣告形參利用解構賦值+預設賦值
function ajax({method='get',data={}){
    //函式傳參解構賦值,相當於let了這個變數;
    console.log(method,data)
}
ajax({
    method:'get',
    data:{id:1}
})

複製程式碼
  • 省略賦值
var arr = [1,2,3]
var [,,j] = arr;
console.log(j)//3 只想取出陣列最後一個
複製程式碼

模版字串

  • 1.可以巢狀變數
  • 2.支援換行
  • 3.可帶一個標籤屬性進行描述,因為我們希望有時候在拼接字串的時候有自己的邏輯
var name = 'xiaoming',age = 9;
var str = `${name}今年${age}歲`
var str1= `${name}
今年${age}歲
`console.log(str)
console.log(str1)

//把老陣列中的每一個元素應設為新陣列中的每一個元素
var users = [{id:1,name:'zfpx1'},{id:2,name:'zfpx2'}]
var newUser = users.map(item=>{
    return `<li>${item.id}:${item.name}</li>`
})
let str = (`
    <ul>
    ${newUser}
    </ul>
`)
console.log(str)


//描述
//帶標籤的模版字串就像一個函式呼叫
//引數:第一個引數是文字的陣列,剩下的依次是模版字串中出現的變數值;可以用剩餘運算子收攏起來
//strings 文字的陣列 指的是 模版字串被變數分割出來的陣列。
function desc(strings,...rest){
    let result = '';
    for(let i =0;i<rest.length;i++){
        result +=(strings[i]+rest[i])
    }
    result += strings[strings.length-1] //strings是被變數分割出來的,所以長度比rest多一個;
    return result;
}
var str = desc`${name}今年{age}歲了`
//str就是desc的返回值



面試:模版字串(ejs等字串模版通用原理)的原理:正則匹配-分組捕獲-替換
var name = 'xiaoming',age = 9;
var tem = "${name}今年${age}歲了";
function replace(tem){
    return tem.replace(/\$\{(\w+)\}/g,function(...args){
            //args[0] 匹配到的整個串
            //args[1] 第一個分組捕獲的
            return eval(args[1]);//替換匹配到的整個串
            })
}
console.log(replace(tem))

複製程式碼

字串新增的方法

  • includes 是否包含
  • startsWith 是否以什麼開頭
  • endsWith 是否以什麼結尾
  • repeat 重複多少遍,返回新的字串
let address1 = 'http://www.baidu.com'
let address2 = 'ftp://www.baidu.com'
if(address1.startsWith('http')){
    console.log('http網址')
}else  if(address1.endsWidth('http')){
    console.log('ftp服務')
}
let filename = 'avatar.jpg';
if(filename.endsWith('jpg') || filename.endWith('png')){
    console.log('圖片')
}

let str = 'zfpx'
str.includes('z')//true 包含

let str2 = str.repeat(3);// zfpxzfpxzfpx 重複三遍,返回新的字串

複製程式碼

func方法(函式傳參、接收引數、剩餘運算子、展開運算子)

  • 預設引數:可以指定預設值,沒傳的話(undefined)就用預設值;指定必傳引數,不傳報錯;解構賦值引數; function ajax(url=new Error('url不能為空'),method='get',dataType='json'){ console.log(url) console.log(method) console.log(dataType) } function ajax1({url=new Error('url不能為空'),method='get',dataType='json'}){ console.log(url) console.log(method) console.log(dataType) }

ajax('/user') ajax1({ url:'/user' })

  • 剩餘操作符,函式接收引數時使用,只能作為函式的最後一個接收引數使用;
//求和
function sum(prefix,...rest){
    let n = rest.reduce((prev,next,nextIndex,origin)=>{
        return prev+next;
    })
    return prefix+n
}
sum('$',1,2,3,4)

//求平均值
function fn(...rest){
    return rest.reduce((prev,next,nextIndex,origin)=>{
        let sum = prev+next;
        if(nextIndex == origin.length-1){
            return sum/origin.length;
        }else{
            return sum;
        }
    })
}
fn(1,2,3,4)

複製程式碼
  • 展開運算子(淺拷貝、合併物件、函式入參)
//陣列
var arr1 = [1,2,3]
var arr2 = [4,5,6]
var arr3 = [...arr1,...arr2]
var arr4 =arr1.concat(arr2)


//物件
var obj1 = {a:1,b:2}
var obj2 = {c:3,d:4}
var obj3 = {
    ...obj1,
    ...obj2
}
var obj4 = Object.assign({},obj1,obj2)
//函式入參
function sum(a,b,c){
    return a+b+c
}
sum(...arr1)

Math.max(1,2,3)
Math.max.apply(null,arr1)
Math.max(...arr1)


前端面試擴充套件:
//深拷貝、淺拷貝
淺拷貝:  ...展開運算子、Object.assign
深拷貝:
JSON.parse(JSON.stringify({home:{city:'beijing'}))
function deepClone(origin){
    let result;
    if(origin instanceof Array){
        result = [];
        for(let i=0;i<origin.length;i++){
            result.push(deepClone(origin[i]))
        }
    }else if(origin instanof Object){
        result  = {};
        for(let key in origin){
            result[key] = deepClone(origin[key])
        }
    }else{
        result = origin
    }
    return result;
}

//reduce 的原理
//reduce 支援兩個引數:第一個引數是函式,第二個引數是初始值(不傳的話預設是陣列第一項)
//主要原理 就是 上一次的執行結果是下一次的初始值。
 var arr = [1,2,3,4]
 arr.reduce((prev,next,nextIndex,origin)=>{
     return prev +next
 },10)  //初始值是10,第一次呼叫prev是10,next是1,nextIndex是0, 最後得到的結果是20 
 
 
Array.prototype.myReduce = function(cb,initVal){
    var prev,nextIndex;
    if(typeof initVal =='undefined'){
        //沒傳的話,初始值是陣列第一項,next的索引是1
        prev = this[0];
        nextIndex = 1;
    }else{
        //傳了的話,初始值是傳入的,next的索引是0
        prev = initVal;
        nextIndex = 0;
    }
    for(var j = nextIndex;j<this.length;j++){
        prev = cb(prev,this[j],j,this)//執行結果是下一次的初始值。
    }
    return prev;
}
 

複製程式碼

arrow箭頭函式

  • this指向上一級作用域的this
  • 沒有arguments
var sum = function(a,b){
    return a+b;
}
//如果只有返回值,沒有函式題程式碼,則可以省略{}
var sum1 = (a,b)=>a+b;
sum1(1,2)

////如果有且只有一個引數,可以省略小括號;
var double = num =>num*2
console.log(double(2))


//this問題,  箭頭函式沒有this,他會使用上級作用域的的this;


 let obj = {
    name:'zfpx',
    getName(){
        console.log(this.name)//this=>obj
    }
 }
 obj.getName()
-------
let obj2 = {
    name:'zfpx',
    getName(){
        //this=>obj
        setTimeout(function () {
            console.log(this.name)//this=>window,   undefined
        },1000)
    }
}
obj2.getName()

---
let obj3 = {
    name:'zfpx',
    getName(){
        //this=>obj
        setTimeout( ()=> {
            //箭頭函式沒有this,他會使用上級作用域的的this
            console.log(this.name)//this=>obj,  zfpx
        },1000)
    }
}
obj3.getName()

---
let obj4 = {
    name:'zfpx',
    getName:()=>{
        console.log(this.name,11111) //this =>window,    undefined
    }
}
obj4.getName()


//箭頭函式的this是定死的,在定義時就定死了,不管在哪裡調,不管誰去調,this都是定義時的外層作用域的this
var obj5 = {
    name:'zfpx',
    getName:()=>{
        console.log(this.name) //this =>window,    undefined
    }
}
var obj6 = {};
obj6.getName = obj5.getName;
obj6.getName();


複製程式碼

相關文章