JavaScript

0、一些概念

(1)JavaScript 中的所有事物都是對象:字符串、數值、數組、函數;此外,JavaScript 允許自定義對象。對象只是一種特殊的數據,對象擁有屬性和方法;即對象只是帶有屬性和方法的特殊數據類型。

  • 布爾型可以是一個對象。數字型可以是一個對象。字符串也可以是一個對象。日期是一個對象。數學和正則表達式也是對象。數組是一個對象。甚至函數也可以是對象。
  • 請不要把字符串、數值和布爾值聲明爲對象!如果通過關鍵詞 “new” 來聲明 JavaScript 變量,則該變量會被創建爲對象:
    var x = new String(); // 把 x 聲明爲 String 對象
    var y = new Number(); // 把 y 聲明爲 Number 對象
    var z = new Boolean(); // 把 z 聲明爲 Boolean 對象
    請避免字符串、數值或邏輯對象,他們會增加代碼的複雜性並降低執行速度。

(2)JavaScript 是面向對象的語言,但 JavaScript 不使用類。在 JavaScript 中,不會創建類,也不會通過類來創建對象(就像在其他面向對象的語言中那樣)。JavaScript 基於 prototype(原型),而不是基於類的。(函數 + prototype 機制)

  • 基於類的是創建模型,基於原型的是經驗模型,前者是現有馬這個概念,纔有胯下之馬這個實體,後者是先有胯下之馬這個實體,纔有馬這個概念。
  • 在思考面向原型的時候,類的概念有是可以的,因爲本質上對象的原型就是類。但是,類構造出對象的這個過程卻要不得,面向原型裏,是由具體對象推導出原型來的。
  • 訪問對象的屬性或者方法時,會訪問其__proto__以及__proto__的__proto__,直到找到這個屬性或者方法爲止,而函數的prototype屬性執行後會返回執行結果的__proto__。

1、apply() 方法與 call() 方法

apply() 方法能劫持另外一個對象的方法,繼承另外一個對象的屬性。

var person = {
    fullName: function (city, country) {
        return this.firstName + " " + this.lastName + "," + city + "," + country;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates"
}
var x = person.fullName.apply(person1, ["Seatle", "USA"]);
// var x = person.fullName.call(person1, "Seatle", "USA");
// 應用輸出:
Bill Gates, Seatle, USA

2、函數節流(throttle)與函數防抖(debounce)

函數節流:限制一個函數在一定時間內只能執行一次;即在一定時間之內,限制一個動作只執行一次。

// 時間戳方案
function throttle(fn, wait) {
    let pre = Date.now();
    return function () {
        let context = this;
        let args = arguments;
        let now = Date.now();
        if (now - pre >= wait) {
            fn.apply(context, args);// args 即上面的 pre,this 是爲了能持有 args 
            pre = Date.now();
        }
    }
}

window.addEventListener("mousemove", throttle(fu, 1000));

函數防抖:短時間內多次觸發同一事件,只執行最後一次,或者只執行最開始的一次,中間的不執行。

/**
   * @desc 函數防抖
   * @param func 目標函數
   * @param wait 延遲執行毫秒數
   * @param immediate true - 立即執行, false - 延遲執行
   */
function debounce(func, wait, immediate) {
    let timer;
    return function () {
        let context = this;
        let args = arguments;

        if (timer) clearTimeout(timer);
        if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, wait);
            if (callNow) func.apply(context, args);
        } else {
            timer = setTimeout(() => {
                func.apply(context, args);
            }, wait)
        }
    }
}

3、數組去重的n種方式

利用數組 filter 方法過濾:

Array.prototype.unique = function unique() {
    var res = this.filter(function (item, index, array) {
        return array.indexOf(item) === index;
    });
    return res;
}

利用對象屬性的唯一性:

Array.prototype.unique = function () {
    var temp = [], hash = {};    // hash 作爲哈希表
    for (var i = 0; i < this.length; i++) {
        if (!hash[this[i]]) {    // 如果哈希表中沒有當前項
            hash[this[i]] = true;
            temp.push(this[i])
        }
    }
    return temp;
}

利用 ES6 set 數據結構:

Array.prototype.unique = function () {
    return Array.from(new Set(this));
}

運行速度差異不大,不過鑑於 set 是 ES6 新加內容,在實際開發環境中,推薦使用穩定性和速度都比較不錯的前兩個方法。

4、解構賦值【ECMAScript 6.0 規範(ES6)】

1、使用數組成員對變量賦值時,優先使用解構賦值:
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
2、函數的參數如果是對象的成員,優先使用解構賦值:
// 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 }) {
}
3TODO: 如果函數返回多個值,優先使用對象的解構賦值,而不是數組的解構賦值。這樣便於以後添加返回值,以及更改返回值的順序:
// bad
function processInput(input) {
  return [left, right, top, bottom];
}
// good
function processInput(input) {
  return { left, right, top, bottom };
}
const { left, right } = processInput(input);
for (const { name, age } of persons) {
  console.log(name);
  console.log(age);
}

5、內置函數

數值方法:

1、toFixed():可把 Number 四捨五入爲指定小數位數的數字
let qqq = 1.234567;
qqq.toFixed(3); // "1.235"

2、toString():返回該數值的字符串格式
qqq.toString(); // "1.2345676"

3、valueOf():返回數值
let aaa = '1.23456789';
aaa.valueOf(); // 1.23456789

數組方法:

1、concat():返回兩個數據經過聯接後的數組
let arr1 = [1,2,3]
let arr2 = [3,2,1]
let arr3 = arr1.concat(arr2) // (6) [1, 2, 3, 3, 2, 1]
arr1 // (3) [1, 2, 3]
arr1 = arr1.concat(arr2)
arr1 // (6) [1, 2, 3, 3, 2, 1]
2、forEach():調用一個函數來處理數組中的每個元素。
3、map():調用一個函數處理數組中的每一個元素,將生成的結果組成一個新的數組,並返回
4、pop():返回數組中的最後一個元素,並刪除
5、push():在數組的最後增加一個元素,並返回新數組的長度
6、splice():向/從數組中添加/刪除項目,然後返回被刪除的項目
7、sort():對數組中的元素排序。
8、reverse():反轉數組元素的順序
let arr = [1,2,3,4,5,6,7,8,9,0]
arr // (10) [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
arr.reverse() // (10) [0, 9, 8, 7, 6, 5, 4, 3, 2, 1]

正則匹配:

1、exec 是 RegExp 類的方法:
/hello/.exec('hello world');
// JavaScript RegExp 對象  https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp

2、match 是 String 類的方法:
'hello world'.match(/'hello'/);

5、get 和 set 方法

getter 是獲取屬性值,setter 是設置屬性值,getter 不帶任何參數,setter 設置鍵值,值以參數的形式傳遞,在 setter 函數體中,一切的 return 都是無效的,當只有 setter 函數時,那這個屬性是隻寫的,當只有 getter 函數時,那這個屬性是隻讀的,同時有 setter、getter 函數,這個屬性可讀可寫。

let o = {
    get x() {
        return 7;
    },
    set x(val) {
        console.info("不能設置x的值");
    }
}
o.x    //7 讀取x值的時候,會使用get方法
o.x = 9  //不能設置x的值 賦值x時,會使用set方法
let p = {
    get() {
        return this._p;
    },
    set(value) {
        value = value === undefined ? 0 : value;
        this._p = value;
        // 悄悄乾點其它的操作
        this.xxxxx(value);
    }
}

參考:
蘇格拉沒有底:https://segmentfault.com/u/sugelameiyoudi_5a3a4031b8a3f/articles

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章