Github每日一題——7.15學(xué)習(xí)記錄

前言


題目來自Daily-Interview-Question 木易楊
歡迎star首懈,加入討論

本文記錄自己對題目的解決方式以及綜合大神們的看法。

題目


1缀台、匹配elective后的數(shù)字輸出(寫出你認(rèn)為的最優(yōu)解法)

https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=&local_province_id=33
https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=800&local_province_id=33
https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=800,700&local_province_id=33

正則表達(dá)式解決方法:

const getUrlValue = function(url){
  let res = url.match(/(?<=elective=)(\d+(,\d+)*)/)
  return res ? res[0].split(',') : []
}

(?<=elective=) 是指匹配以elective=開頭的字符串;
(\d+(, \d+))指匹配數(shù)字開頭,可能不定數(shù)量逗號分隔后是數(shù)字的字符串枫慷。

String.prototype.match()

語法:

str.match(regexp)

參數(shù):
  • 一個(gè)正則表達(dá)式對象
  • 如果傳入一個(gè)非正則表達(dá)式對象,則會(huì)隱式地使用 new RegExp(obj) 將其轉(zhuǎn)換為一個(gè) RegExp(obj)
  • 果你沒有給出任何參數(shù)并直接使用match() 方法 浪规,你將會(huì)得到一 個(gè)包含空字符串的Array[]
返回值:
  • 如果使用g標(biāo)志或听,則將返回與完整正則表達(dá)式匹配的所有結(jié)果(Array),但不會(huì)返回捕獲組罗丰,或者未匹配 null神帅。
  • 如果未使用g標(biāo)志,則僅返回第一個(gè)完整匹配及其相關(guān)的捕獲組(Array)萌抵。 在這種情況下找御,返回的項(xiàng)目將具有如下所述的其他屬性元镀,或者未匹配 null。

URLSearchParams的解決方案:

 new URLSearchParams('https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=800,700&local_province_id=33').get('elective')
urls.forEach(url => {
console.log(new URLSearchParams(url).get('elective').split(','));
});

URLSearchParams

構(gòu)造函數(shù):
  • URLSearchParams()
    返回一個(gè)URLSearchParams對象
方法:
  • URLSearchParams.append()
    插入一個(gè)指定的鍵/值對作為新的搜索參數(shù)霎桅。

  • URLSearchParams.delete()
    從搜索參數(shù)列表里刪除指定的搜索參數(shù)及其對應(yīng)的值栖疑。

  • URLSearchParams.entries()
    返回一個(gè)iterator可以遍歷所有鍵/值對的對象

  • URLSearchParams.get()
    獲取指定搜索參數(shù)的第一個(gè)值。

  • URLSearchParams.getAll()
    獲取指定搜索參數(shù)的所有值滔驶,返回是一個(gè)數(shù)組遇革。

  • URLSearchParams.has()
    返回Boolean判斷是否存在此搜索參數(shù)。

  • URLSearchParams.keys()
    返回iterator 此對象包含了鍵/值對的所有鍵名

  • URLSearchParams.set()
    設(shè)置一個(gè)搜索參數(shù)的新值揭糕,假如原來有多個(gè)值將刪除其他所有的值萝快。

  • URLSearchParams.sort()
    按鍵名排序

  • URLSearchParams.toString()
    返回搜索參數(shù)組成的字符串,可直接使用在URL上著角。

  • URLSearchParams.values()
    返回iterator此對象包含了鍵/值對的所有值揪漩。

不過URLSearchParams對IE的兼容性不友好

URL解決方法:

new URL
("[https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=700,800&local_province_id=33](https://www.xx.cn/api?keyword=&level1=&local_batch_id=&elective=700,800&local_province_id=33)")
.searchParams.get("elective")
.split(",")
.filter(e=>e)
.map(e=>e)

2、模擬實(shí)現(xiàn)一個(gè) localStorage

localStorage

  • 介紹:
    只讀的localStorage 屬性允許你訪問一個(gè)Document源的對象 Storage吏口;其存儲(chǔ)的數(shù)據(jù)能在跨瀏覽器會(huì)話保留奄容。localStorage 類似 sessionStorage,但其區(qū)別在于:存儲(chǔ)在 localStorage 的數(shù)據(jù)可以長期保留产徊;而當(dāng)頁面會(huì)話結(jié)束——也就是說昂勒,當(dāng)頁面被關(guān)閉時(shí),存儲(chǔ)在 sessionStorage 的數(shù)據(jù)會(huì)被清除
    ?
    另外舟铜,localStorage中的鍵值對總是以字符串的形式存儲(chǔ)戈盈。 (需要注意, 和js對象相比, 鍵值對總是以字符串的形式存儲(chǔ)意味著數(shù)值類型會(huì)自動(dòng)轉(zhuǎn)化為字符串類型).

語法:

myStorage = localStorage

示例:

增加一個(gè)數(shù)據(jù)項(xiàng)目

localStorage.setItem('myCat', 'Tom');

讀取 localStorage

let cat = localStorage.getItem('myCat')

移除 localStorage 項(xiàng)

localStorage.removeItem('myCat')

移除所有的 localStorage 項(xiàng)

localStorage.clear()

現(xiàn)在我們知道了localStorage的接口有增加,讀取谆刨,刪除和刪除所有

思路:

先實(shí)現(xiàn)這些功能奕谭,然后掛載到全局變量里面去

來自EnergySUD的解決方案

const localStorageMock = (function() {
    let store = {}
    return {
        getItem: function(key) { return store[key] || null },
        setItem: function(key, value) { store[key] = value.toString() },
        removeItem: function(key) { delete store[key] },
        clear: function() { store = {} },
    }
})()

Object.defineProperty(window, 'localStorage2', {
    value: localStorageMock
})
        
localStorage2.setItem('test', 'test')
console.log(localStorage2.getItem("test"))  //test

localStorage2.removeItem('test')
console.log(localStorage2.getItem("test"))  //null

localStorage2.setItem('test', 'test')
localStorage2.clear()
console.log(localStorage2.getItem("test"))  //null

但是這個(gè)方法有問題,問題在于value的值如果是個(gè)對象痴荐,就跟瀏覽器的表示方式不一樣血柳。

方案二

樓下13834242832有個(gè)解決方案,用String字符串對象解決了上面的問題
同時(shí)用了Map對象來保存鍵值對

'use strict'
const valuesMap = new Map()

class LocalStorage {
  getItem (key) {
    const stringKey = String(key)
    if (valuesMap.has(key)) {
      return String(valuesMap.get(stringKey))
    }
    return null
  }

  setItem (key, val) {
    valuesMap.set(String(key), String(val))
  }

  removeItem (key) {
    valuesMap.delete(key)
  }

  clear () {
    valuesMap.clear()
  }

  key (i) {
    if (arguments.length === 0) {
      throw new TypeError("Failed to execute 'key' on 'Storage': 1 argument required, but only 0 present.") // this is a TypeError implemented on Chrome, Firefox throws Not enough arguments to Storage.key.
    }
    var arr = Array.from(valuesMap.keys())
    return arr[i]
  }

  get length () {
    return valuesMap.size
  }
}
const instance = new LocalStorage()

global.localStorage = new Proxy(instance, {
  set: function (obj, prop, value) {
    if (LocalStorage.prototype.hasOwnProperty(prop)) {
      instance[prop] = value
    } else {
      instance.setItem(prop, value)
    }
    return true
  },
  get: function (target, name) {
    if (LocalStorage.prototype.hasOwnProperty(name)) {
      return instance[name]
    }
    if (valuesMap.has(name)) {
      return instance.getItem(name)
    }
  }
})

Map

Objects 和 maps 的比較
相同點(diǎn):
  • 都允許你按鍵存取一個(gè)值生兆、刪除鍵难捌、檢測一個(gè)鍵是否綁定了值。
不同點(diǎn):
  • 可以通過 size 屬性直接獲取一個(gè) Map 的鍵值對個(gè)數(shù)鸦难,而 Object 的鍵值對個(gè)數(shù)只能手動(dòng)計(jì)算根吁。

  • 一個(gè)Object的鍵只能是字符串,但一個(gè) Map 的鍵可以是任意值合蔽,包括函數(shù)击敌、對象、基本類型拴事。

  • Map 中的鍵值是有序的沃斤,而添加到對象中的鍵則不是圣蝎。因此,當(dāng)對它進(jìn)行遍歷時(shí)衡瓶,Map 對象是按插入的順序返回鍵值徘公。

  • Map 可直接進(jìn)行迭代,而 Object 的迭代需要先獲取它的鍵數(shù)組哮针,然后再進(jìn)行迭代关面。

  • Object 都有自己的原型,原型鏈上的鍵名有可能和你自己在對象上的設(shè)置的鍵名產(chǎn)生沖突十厢。雖然 ES5 開始可以用 map = Object.create(null) 來創(chuàng)建一個(gè)沒有原型的對象等太,但是這種用法不太常見。

  • Map 在涉及頻繁增刪鍵值對的場景下會(huì)有些性能優(yōu)勢蛮放。

來源:Map - JavaScript | MDN

Proxy

語法:
let p = new Proxy(target, handler)
參數(shù):
  • target
    用Proxy包裝的目標(biāo)對象(可以是任何類型的對象澈驼,包括原生數(shù)組,函數(shù)筛武,甚至另一個(gè)代理)。

  • handler
    一個(gè)對象挎塌,其屬性是當(dāng)執(zhí)行一個(gè)操作時(shí)定義代理的行為的函數(shù)徘六。

實(shí)例:
  • 基礎(chǔ)示例

在以下簡單的例子中,當(dāng)對象中不存在屬性名時(shí)榴都,缺省返回?cái)?shù)為37待锈,例子中使用了get
有一種給指定對象掛載了get方法的意思嘴高。

let handler = {
    get: function(target, name){
        return name in target ? target[name] : 37;
    }
};

let p = new Proxy({}, handler);

p.a = 1;
p.b = undefined;

console.log(p.a, p.b);    // 1, undefined

console.log('c' in p, p.c);    // false, 37
  • 無操作轉(zhuǎn)發(fā)代理

在以下例子中竿音,我們使用了一個(gè)原生 JavaScript 對象,代理會(huì)將所有應(yīng)用到它的操作轉(zhuǎn)發(fā)到這個(gè)對象上拴驮。

let target = {};
let p = new Proxy(target, {});

p.a = 37;   // 操作轉(zhuǎn)發(fā)到目標(biāo)

console.log(target.a);    // 37. 操作已經(jīng)被正確地轉(zhuǎn)發(fā)
  • 驗(yàn)證

通過代理春瞬,你可以輕松地驗(yàn)證向一個(gè)對象的傳值。這個(gè)例子使用了 set
有點(diǎn)將函數(shù)掛載到對象上的意思

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }

    // The default behavior to store the value
    obj[prop] = value;
  }
};

let person = new Proxy({}, validator);

person.age = 100;

console.log(person.age); 
// 100

person.age = 'young'; 
// 拋出異常: Uncaught TypeError: The age is not an integer

person.age = 300; 
// 拋出異常: Uncaught RangeError: The age seems invalid
  • 擴(kuò)展構(gòu)造函數(shù)

方法代理可以輕松地通過一個(gè)新構(gòu)造函數(shù)來擴(kuò)展一個(gè)已有的構(gòu)造函數(shù)套啤。這個(gè)例子使用了constructapply宽气。

function extend(sup,base) {
  var descriptor = Object.getOwnPropertyDescriptor(
    base.prototype,"constructor"
  );
  base.prototype = Object.create(sup.prototype);
  var handler = {
    construct: function(target, args) {
      var obj = Object.create(base.prototype);
      this.apply(target,obj,args);
      return obj;
    },
    apply: function(target, that, args) {
      sup.apply(that,args);
      base.apply(that,args);
    }
  };
  var proxy = new Proxy(base,handler);
  descriptor.value = proxy;
  Object.defineProperty(base.prototype, "constructor", descriptor);
  return proxy;
}

var Person = function(name){
  this.name = name
};

var Boy = extend(Person, function(name, age) {
  this.age = age;
});

Boy.prototype.sex = "M";

var Peter = new Boy("Peter", 13);
console.log(Peter.sex);  // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age);  // 13
  • 操作 DOM 節(jié)點(diǎn)

有時(shí)你希望切換兩個(gè)不同的元素的屬性或類名

let view = new Proxy({
  selected: null
},
{
  set: function(obj, prop, newval) {
    let oldval = obj[prop];

    if (prop === 'selected') {
      if (oldval) {
        oldval.setAttribute('aria-selected', 'false');
      }
      if (newval) {
        newval.setAttribute('aria-selected', 'true');
      }
    }

    // The default behavior to store the value
    obj[prop] = newval;
  }
});

let i1 = view.selected = document.getElementById('item-1');
console.log(i1.getAttribute('aria-selected')); // 'true'

let i2 = view.selected = document.getElementById('item-2');
console.log(i1.getAttribute('aria-selected')); // 'false'
console.log(i2.getAttribute('aria-selected')); // 'true'

來源自Proxy - JavaScript | MDN

方案三

wingmeng解決了刷新瀏覽器存儲(chǔ)信息不被清除的問題

!window.localStorage && !function(win) {
  var thousandYears = 1e3 * 365 * 24 * 36e5;

  function getCookies() {
    return document.cookie.match(/([^;=]+)=([^;]+)/g) || [];
  }

  function getExpires(flag) {
    flag = flag || 1;

    return 'expires=' +
      (new Date((+new Date()) + thousandYears * flag)).toUTCString();
  }

  function get(key) {
    var cookies = getCookies();

    for (var i = 0; i < cookies.length; i++) {
      var param = cookies[i].match(/^\s*([^=]+)=(.+)/);

      if (param[1] === String(key)) {
        return decodeURIComponent(param[2]);
      }
    }

    return null;
  }

  function set(key, value, isExpired) {
    document.cookie = [
      key + '=' + encodeURIComponent(value),
      getExpires(isExpired ? -1 : 1),
      'path=/'
    ].join('; ');
  }

  function remove(key) {
    set(key, '', true);
  }

  function clear() {
    var cookies = getCookies();

    for (var i = 0; i < cookies.length; i++) {
      var key = cookies[i].match(/^\s*([^=]+)/)[1];
      remove(key);
    }
  }

  // 注冊到 window 對象上
  win.localStorage = {
    getItem: get,
    setItem: set,
    removeItem: remove,
    clear: clear
  };
}(window);

也可以看一下 MDN LocalStorage實(shí)現(xiàn)

未完待續(xù)
每日更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市潜沦,隨后出現(xiàn)的幾起案子萄涯,更是在濱河造成了極大的恐慌,老刑警劉巖唆鸡,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涝影,死亡現(xiàn)場離奇詭異,居然都是意外死亡争占,警方通過查閱死者的電腦和手機(jī)燃逻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門序目,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唆樊,你說我怎么就攤上這事宛琅。” “怎么了逗旁?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵嘿辟,是天一觀的道長。 經(jīng)常有香客問我片效,道長红伦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任淀衣,我火速辦了婚禮昙读,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘膨桥。我一直安慰自己蛮浑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布只嚣。 她就那樣靜靜地躺著沮稚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪册舞。 梳的紋絲不亂的頭發(fā)上蕴掏,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機(jī)與錄音调鲸,去河邊找鬼盛杰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛藐石,可吹牛的內(nèi)容都是我干的即供。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼于微,長吁一口氣:“原來是場噩夢啊……” “哼募狂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起角雷,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤祸穷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后勺三,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雷滚,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年吗坚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祈远。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呆万。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖车份,靈堂內(nèi)的尸體忽然破棺而出谋减,到底是詐尸還是另有隱情,我是刑警寧澤扫沼,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布出爹,位于F島的核電站,受9級特大地震影響缎除,放射性物質(zhì)發(fā)生泄漏严就。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一器罐、第九天 我趴在偏房一處隱蔽的房頂上張望梢为。 院中可真熱鬧,春花似錦轰坊、人聲如沸铸董。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粟害。三九已至,卻和暖如春樊零,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孽文。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工驻襟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芋哭。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓沉衣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親减牺。 傳聞我的和親對象是個(gè)殘疾皇子豌习,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354