前端知識海底撈之JS

AMD CMD CommonJS

/* AMD是RequireJS對模塊化的定義
 * CMD是seaJS對模塊化的定義
 * CommonJS是Node對模塊化的規(guī)范
 **/

/* AMD 依賴關(guān)系前置 */
define(['./a', './b'], function (a, b) {
    a.something();
    b.something();
})

/* CMD 按需加載栅葡,依賴就近 */
define(function (require, exports, module) {
    var a = require('./a');
    a.something();

    var b = require('./b');
    b.something();
})

阻止默認行為和阻止冒泡

function stopDefault( e ) {
    // 阻止默認瀏覽器動作(W3C)
    if ( e && e.preventDefault ) {
        e.preventDefault();
    } else {
        // IE中阻止函數(shù)器默認動作的方式
        window.event.returnValue = false;
    }
    return false;
}

function stopBubble(e) {
    // 如果提供了事件對象植兰,則這是一個非IE瀏覽器
    if ( e && e.stopPropagation ) {
        // 因此它支持W3C的stopPropagation()方法
        e.stopPropagation();
    } else {
        // 否則仇祭,我們需要使用IE的方式來取消事件冒泡
        window.event.cancelBubble = true;
    }
}

JS數(shù)組

slice實現(xiàn)淺拷貝
var arr = ['old', 1, true, null, undefined];

var new_arr = arr.slice();

new_arr[0] = 'new';

console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]
concat實現(xiàn)淺拷貝
var arr = ['old', 1, true, null, undefined];

var new_arr = arr.concat();

new_arr[0] = 'new';

console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]

以上兩種方法只是淺拷貝感凤,如果數(shù)組元素是基本類型鳍寂,就會拷貝一份新的苍在;但是如果數(shù)組元素是對象或者數(shù)組,就只會拷貝引用(類似指針)晃虫,修改其中一個就會影響另外一個皆撩。

var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];

var new_arr = arr.concat();

new_arr[0] = 'new';
new_arr[3][0] = 'new1';

console.log(arr) // ["old", 1, true, ['new1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]
JSON.stringify 實現(xiàn)數(shù)組深拷貝
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];

var new_arr = JSON.parse(JSON.stringify(arr));

new_arr[0] = 'new';
new_arr[3][0] = 'new1';

console.log(arr) // ["old", 1, true, ['old1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]
手動實現(xiàn)深淺拷貝
/*淺拷貝*/
var shallowCopy = function (obj) {
    // 判斷是否是數(shù)組或者對象
    if (typeof obj !== 'object') {
        return
    }
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

/*深拷貝*/
var deepCopy = function (obj) {
    if (typeof obj !== 'object') {
        return
    }
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj
}
數(shù)組去重
/* filter + indexOf */
function unique (arr) {
    var res = arr.filter(function (item, index, array) {
        return array.indexOf(item) === index;
    })
    return res;
}

/* ES6 */
function unique (arr) {
    return [... new Set(arr)];
}
打亂數(shù)組的方法
var arr = [];
for (var i = 0; i < 100; i++) {
    arr[i] = i;
}

arr.sort(function () {
    return 0.5 - Math.random();
});
數(shù)組扁平化
  let arr = [1, [2, [3, 4]]];

  function flatten(arr) {
    while (arr.some(item => Array.isArray(item))) {
      arr = [].concat(...arr);
    }
    return arr;
  }

  console.log(flatten(arr))

柯里化

執(zhí)行add(1,2,3)(2)()就能輸出1+2+3+2=8。函數(shù)柯里化

const adder = function () {
    let _args = []; // 閉包保留了對 _args 的引用
    return function () {
      console.log(arguments)
      if (arguments.length === 0) {
        return _args.reduce(function (a, b) {
          return a + b;
        });
      }
      [].push.apply(_args, arguments);
      return arguments.callee;
    }
  };
  const sum = adder();

  console.log(sum);     // Function

  sum(100, 200)(300);    // 調(diào)用形式靈活哲银,一次調(diào)用可輸入一個或者多個參數(shù)扛吞,并且支持鏈式調(diào)用
  sum(400);
  console.log(sum());   // 1000 (加總計算)

異步函數(shù)

async關(guān)鍵詞定義的函數(shù)聲明了一個可以異步執(zhí)行的函數(shù),返回一個AsyncFunction類型的對象荆责。淺談Async/Await

async

async—聲明一個異步函數(shù) (async function someName() {...})

  • 自動將常規(guī)函數(shù)轉(zhuǎn)換成Promise滥比,返回值也是一個 Promise 對象;
  • 只有async 函數(shù)內(nèi)部的異步操作執(zhí)行完做院,才會執(zhí)行 then方法指定的回調(diào)函數(shù)盲泛;
  • 異步函數(shù)內(nèi)部可以使用await濒持。
await

await—暫停異步的功能執(zhí)行(var result = await someAsyncCall() {...})

  • 放置在Promise調(diào)用之前,await強制其他代碼等待寺滚,直到Promise完成并返回結(jié)果柑营;
  • 只能與Promise 一起使用,不適用與回調(diào)村视;
  • 只能在async函數(shù)內(nèi)部使用由境。
function fetchTextByPromise () {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve('es8');
      }, 2000);
    });
  }

  async function sayHello () {
    const externalFetchedText = await fetchTextByPromise();
    console.log(`Hello, ${externalFetchedText}`);
  }
  sayHello();

bind,call蓖议,apply

call

call()方法調(diào)用一個函數(shù), 其具有一個指定的this值和分別地提供的參數(shù)(參數(shù)的列表)。

thisArg
  • fun函數(shù)運行時指定的this值讥蟆。需要注意的是勒虾,指定的this值并不一定是該函數(shù)執(zhí)行時真正的this值;
  • 如果這個函數(shù)處于非嚴格模式下瘸彤,則指定為nullundefinedthis值會自動指向全局對象(瀏覽器中就是window對象)修然;
  • 值為原始值(數(shù)字,字符串质况,布爾值)的this會指向該原始值的自動包裝對象愕宋。
arg1, arg2, ...
  • 指定的參數(shù)列表。
 var foo = {
    value: 'fooValue'
  }

  function bar() {
    var value = 'barValue'
    console.log(this.value)
  }

  bar.call(foo) // 'fooValue'
call的polyfill
  • 將函數(shù)設(shè)為對象的屬性
  • 執(zhí)行該函數(shù)
  • 刪除該函數(shù)
 /*
  * 將函數(shù)設(shè)為對象的屬性 foo.bar
  * 執(zhí)行該函數(shù) foo.bar()
  * 刪除該函數(shù) delete foo.bar
  **/

  Function.prototype.myCall = function (con) {
    var context = con || window
    var args = []
    for (var i = 1, len = arguments.length; i < len; i++) {
      args.push('arguments[' + i + ']')
    }
    context.fn = this
    var result = eval('context.fn(' + args + ')')
    delete  context.fn
    return result
  }
apply

call()方法的作用和 apply() 方法類似结榄,區(qū)別就是call()方法接受的是參數(shù)列表中贝,而apply()方法接受的是一個參數(shù)數(shù)組。

apply的polyfill
  Function.prototype.myApply = function (con, arr) {
    var context = con || window
    context.fn = this
    var result
    if (!arr) {
      result = context.fn()
    } else {
      var args = []
      for (var i = 0; i < arr.length; i++) {
        args.push(arr[i])
      }
      result = eval('context.fn(' + args + ')')
    }
    delete context.fn
    return result
  }
bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
  • 調(diào)用綁定函數(shù)時作為this參數(shù)傳遞給目標函數(shù)的值臼朗。 如果使用new邻寿,new運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象的實例。運算符構(gòu)造綁定函數(shù)视哑,則忽略該值绣否。
  • 當使用bindsetTimeout中創(chuàng)建一個函數(shù)(作為回調(diào)提供)時,作為thisArg傳遞的任何原始值都將轉(zhuǎn)換為object挡毅。
  • 如果沒有提供綁定的參數(shù)蒜撮,則執(zhí)行作用域的this被視為新函數(shù)的thisArg
arg1, arg2, ...

當綁定函數(shù)被調(diào)用時跪呈,這些參數(shù)將置于實參之前傳遞給被綁定的方法段磨。

bind的polyfill
 Function.prototype.myBind = function (context) {

    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable")
    }

    var self = this
    var args = Array.prototype.slice.call(arguments, 1)

    var fNOP = function () {}

    var fBound = function () {
      var bindArgs = Array.prototype.slice.call(arguments)
      self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs))
    }

    fNOP.prototype = this.prototype
    fBound.prototype = new fNOP()
    return fBound
  }

詳解:JavaScript 之 call和apply,bind 的模擬實現(xiàn)

new

  • 新生成了一個對象耗绿;
  • 鏈接到原型薇溃;
  • 綁定this
  • 返回新對象缭乘。
new的polyfill
function objectFactory() {
    var obj = new Object()
    var constructor = [].shift.call(arguments)
    obj.__proto__ = constructor.prototype
    console.log(obj)
    var result = constructor.apply(obj, arguments)
    console.log(result)
    return typeof result === 'object' ? result : obj
    // 判斷返回的值是不是一個對象沐序,如果是一個對象琉用,我們就返回這個對象,如果不是策幼,我們該返回什么就返回什么邑时。  
}

instanceof

instanceof可以正確的判斷對象的類型,因為內(nèi)部機制是通過判斷對象的原型鏈中是不是能找到類型的 prototype特姐。

instanceof的polyfill
  function myInstanceOf(left, right) {
    // 獲得類型的原型
    var prototype = right.prototype
    // 獲得對象的原型
    left = left.__proto__
    // 判斷對象的類型是否等于類型的原型
    while (true) {
      if (left === null)
        return false
      if (prototype === left)
        return true
      left = left.__proto__
    }
  }

檢驗類型的方法

千萬不要使用typeof來判斷對象和數(shù)組晶丘,因為這種類型都會返回object

  • typeof:是判斷基本類型的Boolean唐含,Number浅浮,symbolundefined捷枯,String滚秩,Symbol。對于引用類型:除function淮捆,都返回object郁油,null返回object
  • instanceof:用來判斷A是否是B的實例攀痊,instanceof檢查的是原型桐腌。
  • toString:是Object的原型方法,對于Object對象苟径,直接調(diào)用toString() 就能返回[Object Object] 案站。而對于其他對象,則需要通過call /apply來調(diào)用才能返回正確的類型棘街。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嚼吞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蹬碧,更是在濱河造成了極大的恐慌舱禽,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恩沽,死亡現(xiàn)場離奇詭異誊稚,居然都是意外死亡,警方通過查閱死者的電腦和手機罗心,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門里伯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渤闷,你說我怎么就攤上這事疾瓮。” “怎么了飒箭?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵狼电,是天一觀的道長蜒灰。 經(jīng)常有香客問我,道長肩碟,這世上最難降的妖魔是什么强窖? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮削祈,結(jié)果婚禮上翅溺,老公的妹妹穿的比我還像新娘。我一直安慰自己髓抑,他們只是感情好咙崎,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吨拍,像睡著了一般褪猛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上密末,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音跛璧,去河邊找鬼严里。 笑死,一個胖子當著我的面吹牛追城,可吹牛的內(nèi)容都是我干的刹碾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼座柱,長吁一口氣:“原來是場噩夢啊……” “哼迷帜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起色洞,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤戏锹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后火诸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锦针,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年置蜀,在試婚紗的時候發(fā)現(xiàn)自己被綠了奈搜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡盯荤,死狀恐怖馋吗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秋秤,我是刑警寧澤宏粤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布脚翘,位于F島的核電站,受9級特大地震影響商架,放射性物質(zhì)發(fā)生泄漏堰怨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一蛇摸、第九天 我趴在偏房一處隱蔽的房頂上張望备图。 院中可真熱鬧,春花似錦赶袄、人聲如沸揽涮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒋困。三九已至,卻和暖如春敬辣,著一層夾襖步出監(jiān)牢的瞬間雪标,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工溉跃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留村刨,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓撰茎,卻偏偏與公主長得像嵌牺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子龄糊,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

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

  • 本文為阮一峰大神的《ECMAScript 6 入門》的個人版提純逆粹! babel babel負責將JS高級語法轉(zhuǎn)義,...
    Devildi已被占用閱讀 1,972評論 0 4
  • CSS 選擇器的分類 不同級別:總結(jié)排序:!important > 行內(nèi)樣式 > ID選擇器 > 類選擇器 > 標...
    小小的白菜閱讀 536評論 0 7
  • 1 凌晨一點炫惩,我還沒睡沉僻弹,小家伙突然“哇哇”大哭起來。我心一緊他嚷,匆忙起身奢方,開燈。 寶寶哭的異常的慘烈爸舒,閉著眼睛蟋字,兩...
    YIBAO閱讀 755評論 8 4
  • 隨手拈來的文字我沒有鹊奖,走心的隨筆卻成了我的偏愛。 偶遇長沙的初雪涂炎,兜轉(zhuǎn)讀研的生活忠聚。前兩天剛剛結(jié)束了第一學期的課程设哗,...
    岔子小姐閱讀 211評論 0 0