夯實基礎,徹底掌握js的核心技術(四):ES5、ES6對象方法詳解

ES5 Object 對象方法擴展

ES5給Object擴展了一些靜態方法,常用的2個

  1. Object.create(prototype,[descriptors])

作用:以指定對象爲原型創建新的對象<br />爲新對象指定新的屬性,並對屬性進行描述

  • value: 指定值
  • writable: 標識當前屬性值是否是可修改的,默認爲false
  • configurable: 標識當前屬性是否可以被刪除,默認爲false
  • enumerable: 標識當前屬性是否能用 for in 枚舉 默認爲false
  1. Object.defineProperties(object, descriptors)

作用: 爲指定對象定義擴展多個屬性

  • get: 用來獲取當前屬性值的回調函數
  • set: 修改當前屬性值的觸發的額回調函數,並且實參即爲修改後的值
  • 存取器屬性:setter,getter一個用來存值,一個用來取值

ES5數組的擴展

  1. Array.prototype.indexOf(value) : 得到值在數組中的第一個下標
  2. Array.prototype.lastIndexOf(value): 得到值在數組中的最後一個下標
  3. Array.prototype.forEach(function(item, index){}): 遍歷數組
  4. Array.prototype.map(function(item, index){}): 遍歷數組返回一個新的數組,返回加工後的值
  5. Array.prototype.filter(function(item, index){}): 遍歷過濾出一個新的子數組,返回條件爲true的值
var arr = [2, 4, 3, 2, 6, 5, 4]
console.log(arr.indexOf(4)) //1
console.log(arr.lastIndexOf(4)) // 7

arr.forEach(function(item, index) {
    console.log(item, index)
})

var arr1 = arr.map(function(item, index) {
return item + 10
})
console.log(arr1) // [12, 14, 13, 12, 16, 15, 14]

var arr2 = arr.filter(function(item, index) {
return item > 3
})
console.log(arr2)  //[4, 6, 5, 4]

ES5函數的擴展

  1. Function.prototype.bind(obj);

作用:將函數內的this綁定爲obj,並並將函數返回<br />bind的點: 綁定完this不會立即調用當前函數,而是將函數返回<br />bind傳參數的方式同call一樣

  1. 區別bind()與call() apply()

都能指定函數中的this<br />call()/apply()是立即調用函數<br />bind()是將函數返回

var obj = {username: 'lanfeng'}
function foo(data) {
    console.log(this, data)
}
foo(); //window

//傳人蔘數的形式
foo.call(obj, 33) // 直接從第二個參數開始,依次傳入
foo.apply(obj, [33]) //第二個參數必須是數組,傳入參數放在數組裏
//bind的點: 綁定完this不會立即調用當前函數,而是將函數返回
foo.bind(obj)()

// ----------
var obj = {username: 'lanfeng'}
setTimeout(function() {
    console.log(this) //obj
}.bind(obj), 1000)

let、const 關鍵字

let 關鍵字

  1. 作用:與var類似,用於聲明一個變量
  2. 特點:<br />
  • 在塊作用域內有效
  • 不能重複聲明
  • 不會預處理,不存在提升
  1. 應用:
  • 循環遍歷加監聽
  • 使用let取代var趨勢
let username = 'lanfeng'

#### const 

1. 作用:定義一個常量
1. 特點:
- 不能修改
- 其它特點同let
3. 應用: 

保存不用改變的數據

### ES6箭頭函數

1. 作用: 定義匿名函數
1. 基本語法:
- 沒有參數:()=> console.log('xxxx') , 小括號不能省略
- 一個參數:i => i+2
- 大於一個參數:(i, j) => i + j
- 函數體不用大括號:默認返回結果
- 函數體如果有多個語句,需要用{}包圍,若有需要返回的內容,需要手動返回
- 使用場景: 多用來定義回調函數
3. 箭頭函數的特點:
- 簡潔
- 箭頭函數沒有自己的this,箭頭函數的this不是調用的時候決定的,而是定義的時候處在的對象就是它的額this
- 擴展理解:外層函數的this看外層是否有函數,如果有,外層函數的this就是內部箭頭函數的this,如果沒有,則this是window
```javascript
let fun = () => console.log('我是箭頭函數')
fun();

//形參的情況
// 1. 沒有形參的時候,小括號不能省略
let fun1 = ()=> console.log('我是箭頭函數')

// 2. 只有一個形參的時候,小括號可以省略
let fun2 = (a) => console.log(a)
fun2('langfeng')

//3. 兩個及兩個以上的形參的時候,小括號不能省略
let fun3 = (x, y) => console.log(x, y)
fun3(25, 36)

//  函數體的情況
// 1. 函數體只有一條語句或者是表達式的時候,大括號可以省略,會自動返回語句執行的結果或者是表達式的結果
    let fun4 = (x, y) => x+y
  console.log(fun4(24, 36))
// 2. 函數體不止一條語句或者是表達式的額情況,{}不可以省略
let fun5 = (x, y) => {
  console.log(x, y)
  return x + y  
}
console.log(fun5(35, 49))


ES6 promise對象

  1. 理解:
  • promise對象:代表了未來某個將要發生的事件(通常是一個異步操作)
  • 有了promise對象,可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數
  • ES6的promise是一個構造函數,用來生成promise實例
  1. 創建promise基本步驟(2步)
  • 創建promise對象
let promise = new Promise((resolve, reject)) => {
//初始化promise狀態爲pending
//執行異步操作
if(異步操作成功) {
resolve(value)  //修改promise的狀態爲fullfilled
} else {
reject(errMsg) //修改promise的狀態爲rejected
}
}
  • 調用promise的then()
promise.then(
    result => console.log(result),
  errorMsg => alert(errorMsg)
)
  1. promise對象的三個狀態
  • pending: 初始化狀態
  • fullfilled: 成功狀態
  • rejected: 失敗狀態

ES6中的Symbol

  1. 概念:ES6中的添加了一種原始數據類型symbol(已有的原始數據類型:String, Number, boolean, undefined, null,Object)
  2. 特點:
  • symbol屬性對應的值是唯一的,解決命名衝突問題
  • symbol值不能與其它數據進行計算,包括同字符串拼串
  • for in, for of遍歷時不會遍歷symbol屬性
  1. 使用:
  • 調用symbol函數到symbol值
let symbol = Symbol();
let obj = {}
obj[symbol] = 'hello'
  • 傳參標識
let symbol = Symbol('one')
let symbol2 = Symbol('two')
console.log(symbol) // Symbol('one')
console.log(symbol2)  // Symbol('two')
  • 內置Symbol值

除了定義自己使用的Symbol值以外,ES6還提供了11個內置的Symbol值,指向語言內部使用的方法<br />Symbol.iterator<br />對象的Symbol.iterator屬性,指向該對象的默認遍歷器方法<br />

ES6中的async函數

  1. 概念:真正意義上去解決異步回調的問題,同步流程表達異步操作
  2. 本質:Generator的語法糖
  3. 語法:
async function foo() {
    await 異步操作
  await 異步操作
}
  1. 特點:
  • 不需要Generator去調用next方法,遇到await等待,當前的異步操作完成就往下執行
  • 返回的總是Promise對象,可以用then方法進行下一步操作
  • async 取代Generator函數的星號*,await取代Generator的yield
  • 語意上更爲明確,使用簡單

ES6中的class類

  1. 通過class定義類實現類的繼承
  2. 在類中通過constructor定義構造函數
  3. 通過new來創建類的實例
  4. 通過extends來實現類的繼承
  5. 通過super調用父類的構造方法
  6. 重寫從父類中繼承的一般方法
class Person {
  //類的構造方法
    constructor(name, age) {
    this.name = name;
    this.age = age
  }
  showName() {
    console.log(this.name)
  }
}
let person = new Person('kobe', 39)
console.log(person)
console.log(person.showName())

//子類
class StartPerson extends Person {
    constructor(name, age) {
    super(); //調用父類構造方法
  }
}
let startPerson = new StartPerson('lanfeng', 28, 10000)
console.log(startPerson.showName()) // lanfeng

ES6中字符串的擴展

  1. includes(str): 判斷是否包含指定的字符串
  2. startsWith(str): 判斷是否以指定字符串開頭
  3. endsWith(str): 判斷是否以指定字符串結尾
  4. repeat(count): 重複指定次數

ES6中數組擴展方法

  1. Array.from(v): 將僞數組對象或者可遍歷轉換爲真熟組
  2. Array.of(v1, v2, v3): 將一系列值轉換成數組
  3. find(function(value, index, arr) { return true }) : 找出第一個滿足條件返回true的元素
  4. findIIndex(function(value, index, arr) { retturn true }): 找出第一個滿足條件返回true的元素下標

ES6中對象擴展方法

  1. Object.is(v1, v2)

判斷2個數據是否完全相等

  1. Object.assign(target, source1, source2...)

將源對象的屬性複製到目標對象上

  1. 直接操作proto屬性

let obj2 = {}<br />obj2._ proto_ = obj1<br />

console.log(Object.is(0, -0)) // false
console.log(Object.is(NaN, NaN)) // true

數組和對象的克隆

  1. 對象複製
let obj = { username: 'lanfeng'}
let obj1 = obj; // obj1 複製了obj在堆內存的引用
  1. 常用的拷貝技術
  • arr.concat():數組淺拷貝
  • arr.slice(): 數組淺拷貝
  • JSON.parse(JSON.stringify(arr/obj)) : 數組或對象深拷貝
  • 淺拷貝包含函數數據的對象/數組
  • 深拷貝包含函數數據的對象/數組

拷貝數據:

  1. 基本數據類型:拷貝後會生成一份新的數據,修改拷貝後的數據不會影響原數據
  2. 對象/數組:拷貝後不會生成新的數據,而是拷貝的是引用,修改拷貝以後的數據會影響原來的數據
//拷貝數組/對象,沒有生成新的數組而是複製了一份引用
let obj = {username: 'lanfeng', age: 30}
let obj1 = obj
console.log(obj1) // {username: "lanfeng", age: 30} 
obj1.username = 'qiuqiu'
console.log(obj.username) //qiuqiu

拷貝數據的方法:

  • 直接賦值給一個變量. // 淺拷貝
  • Object.assgin()
  • Array.prototype.concat() // 淺拷貝
  • Array.prototype.slice() // 淺拷貝
  • JSON.parse(JSON.stringfy()) //深拷貝,拷貝的數據裏面不能有函數數據,處理不了
let obj = {username: 'lanfeng'}
let obj2 = Object.assign(obj)
console.log(obj2) // {username: "lanfeng"}
obj2.username = 'qiuqiu'
console.log(obj) // {username: "qiuqiu"}

// ---------
let arr = [1, 3, {username:'lanfeng'}]
let arr2 = arr.concat()
// console.log(arr2) //[1, 3, {username:'lanfeng'}]
arr2[1] = 'a'
console.log(arr)  //[1, 3, {username:'lanfeng'}]
arr2[2].username = 'qiuqiu'
console.log(arr)  //[1, 3, {username:'qiuqiu'}]

// ------
let arr = [1, 3, {username:'lanfeng'}]
let arr4 = JSON.parse(JSON.stringify(arr))
arr4[2].username = 'lanfeng2'
console.log(arr)  // [1, 3, {username:'lanfeng'}]


淺拷貝(對象/數組)<br />特點:拷貝的引用,修改拷貝以後會影響原數據<br />深拷貝(深度克隆):拷貝的時候生成新的數據,修改拷貝以後不會影響原數據

在實現深拷貝之前,我們需要掌握以下知識點<br />如果判斷數據類型:

  1. typeof返回的數據類型:String, Number, Boolean, undefined, object,function
  2. Object.prototype.toString.call(obj)
let result = 'abcd'
result = null;
result = [1, 3]
console.log(Object.prototype.toString.call(result).slice(8, -1)); // Array

for in 循環 對象(屬性名) 數組(下標)

let obj = {username: 'lanfeng', age: 39}
for(let i in obj) {
    console.log(i)
}
let arr = [1,3, 'abc']
for(let i in arr) {
    console.log(i)
}

定義檢測數據類型的功能函數

function checkType(target) {
    return Object.prototype.toString.call(result).slice(8, -1)
}

實現深度克隆 ,一般針對數組或者對象

function checkedType(target) {
    return Object.prototype.toString.call(target).slice(8, -1)
}

function clone(target) {
    // 首先判斷拷貝數據的類型
  //
  let result, targetType = checkedType(target);
  if(targetType === 'Object') {
    result = {};
  } else if(targetType === 'Array') {
    result = [];
  } else {
    return target
  }
  
  // 遍歷目標數據
  for(let i in target) {
    // 獲取遍歷數據結構的每一項值
    let value = target[i]
    
    // 判斷目標結構裏的每一項值是否存在對象或數組
    if(checkedType(value) === 'Object' || checkedType(value) === 'Array') {
        // 繼續遍歷獲取到value值
      result[i] = clone(value)
    } else {
      // 獲取都的value值是最基本的數據類型或者是函數
        result[i] = value
    }
  }
  return result 
}
let arr3 = [1,2, {username: 'lanfeng'}]
let arr4 = clone(arr3)
console.log(arr4)
arr4[2].username = 'qiuqiu'
console.log(arr3, arr4)

運行結果如下圖:<br />

ES6中的set、map容器

  1. Set容器: 無序不可重複的多個value的集合體
  • Set()
  • Set(array)
  • add(value)
  • delete(value)
  • has(key)
  • clear()
  • size
let set = new Set([1,2,4,2,5])
console.log(set)
  1. Map容器:無序的key不重複的多個key-value的集合體
  • Map()
  • Map(array)
  • set(key, value) //添加
  • get(key)
  • delete(key)
  • has(key)
  • clear()
  • size

ES6中的for of

for (let value of target) {} 循環遍歷

  • 遍歷數組
  • 遍歷Set
  • 遍歷Map
  • 遍歷字符串
  • 遍歷僞數組
let set = new Set([1,2,4,5,2,3])
let arr = []
for(let i of set) {
    arr.push(i)
}

如果想了解更多,請掃描二維碼,關注公衆號:<br />
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章