成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【資源集合】 ES6 元編程(Proxy & Reflect & Symbol)

aikin / 3621人閱讀

摘要:理解元編程和是屬于元編程范疇的,能介入的對(duì)象底層操作進(jìn)行的過(guò)程中,并加以影響。元編程中的元的概念可以理解為程序本身。中,便是兩個(gè)可以用來(lái)進(jìn)行元編程的特性。在之后,標(biāo)準(zhǔn)引入了,從而提供比較完善的元編程能力。

導(dǎo)讀

幾年前 ES6 剛出來(lái)的時(shí)候接觸過(guò) 元編程(Metaprogramming)的概念,不過(guò)當(dāng)時(shí)還沒(méi)有深究。今天在應(yīng)用和學(xué)習(xí)中不斷接觸到這概念,比如 mobx 5 中就用到了 Proxy 重寫(xiě)了 Observable 對(duì)象,覺(jué)得有必要梳理總結(jié)一下。

本文不生產(chǎn)代碼,只當(dāng)代碼、文檔的搬運(yùn)工。所以本文并非是一篇傳統(tǒng)意義上的教程,更類似于 github awesome 這樣列表文章。

1、理解元編程

Symbol、Reflect 和 Proxy 是屬于 ES6 元編程范疇的,能“介入”的對(duì)象底層操作進(jìn)行的過(guò)程中,并加以影響。元編程中的 的概念可以理解為 程序 本身。

”元編程能讓你擁有可以擴(kuò)展程序自身能力“。這句話還是很抽象,初學(xué)者該怎么理解呢?

我也理解了半天,想到了下面的例子:

就好比你原本是公司的部門的大主管,雖然你能力很強(qiáng),但也必須按照規(guī)章制度做事,比如早上 8 點(diǎn)必須到公司,否則你就要扣績(jī)效;而后來(lái)公司基本規(guī)定靈活了,每個(gè)部門可以自己制定打卡制度,此時(shí)身為主管的你,依據(jù)公司該基本規(guī)定,制定自己部門的考勤制度,本部門的職工可以 9 點(diǎn)來(lái)公司,還可以不打卡!(當(dāng)然還可以制定其他規(guī)定)

在這個(gè)例子中:

整個(gè)公司“就相當(dāng)于 JS 引擎

公司的基本規(guī)章制度“就相當(dāng)于 JS 運(yùn)行機(jī)制和語(yǔ)法,員工辦事最低要求就是遵照公司的規(guī)章制度

在此基礎(chǔ)上,你擁有管理部門的權(quán)力,負(fù)責(zé)開(kāi)發(fā)并維護(hù)一些產(chǎn)品“,這種行為就相當(dāng)于平時(shí)普通的編程;

公司的基本規(guī)定變靈活之后,你除了擁有以前管理員工的權(quán)力之外,”還擁有更改制度(針對(duì)該部門)的能力,這樣就可以從制度層面影響員工的最低要求行為“,這里更改規(guī)章制度就相當(dāng)于 元編程 了;

這里的例子不一定準(zhǔn)確,是我個(gè)人的理解,權(quán)做參考,也可以去看看知乎上 怎么理解元編程? 的問(wèn)答。

借助這個(gè)例子理解元編程,我們能感知在沒(méi)有元編程能力的時(shí)候,就算你編程能力很厲害,但終究“孫悟空翻不出五指山”;而掌握了元編程能力之后,就差上天了,“給你一個(gè)支點(diǎn),你就能撬動(dòng)地球”,能力大大擴(kuò)增。

簡(jiǎn)言之,元編程讓你具備一定程度上改變現(xiàn)有的程序規(guī)則層面的能力?;蛘哒f(shuō),元編程可以讓你以某種形式去影響或更改程序運(yùn)行所依賴的基礎(chǔ)功能,以此獲得一些維護(hù)性、效率上的好處。

Javascript 中,eval、new Function()便是兩個(gè)可以用來(lái)進(jìn)行元編程的特性。不過(guò)因?yàn)樾阅芎涂删S護(hù)的角度上,這兩個(gè)特性還是不要用為妙。

在 ES6 之后,標(biāo)準(zhǔn)引入了 Proxy & Reflect & Symbols,從而提供比較完善的元編程能力。

2、學(xué)習(xí) ES6 元編程的資源

我原本也想仔細(xì)講講 ES6 中 Symbol、ProxyReflect 的基本概念和使用的,但網(wǎng)上這方面的文章不要太多,覺(jué)得重復(fù)碼字也沒(méi)有太必要。這里著重推薦幾篇,分為教程類和手冊(cè)類,通讀完之后應(yīng)該就掌握差不多了。

元編程在 ES6 體現(xiàn)最為突出的是 Proxy 的應(yīng)用,目前我所找的文章也多偏向 Proxy。

原理教程類

深入淺出ES6(十二):代理 Proxies:ES6 深入淺出系列,個(gè)人推薦認(rèn)真讀完該文章。本文的作者實(shí)現(xiàn)了 ES6 的 Reflect 特性,所以他對(duì) ES6 這兩個(gè)特性理解是最為深刻的,他的文章自然要深度閱讀。

ES6 Proxies in Depth:和其他教程相比,該文章篇幅稍微短一些,能較為快速得掌握概念和一些實(shí)際應(yīng)用。

Metaprogramming with proxies:來(lái)自 《Exploring ES6》書(shū)籍摘選,基礎(chǔ)入門。

Chapter 7: Meta Programming:經(jīng)典的 《You Don"t Know JS》系列文章,深入淺出,文章夠長(zhǎng),需要一些耐心。

Metaprogramming in ES6: Symbols and why they"re awesome:本篇就是基于 Symbols、Reflect、Proxy 等實(shí)現(xiàn)元編程的教程系列教程,內(nèi)容也足夠詳實(shí)。

ES6學(xué)習(xí)筆記: 代理和反射:非常詳實(shí)地整理了 ProxyReflect 相關(guān)的知識(shí)點(diǎn),只是閱讀起來(lái)略微枯燥。

應(yīng)用教程類

ES6 Features - 10 Use Cases for Proxy:收集了 10 個(gè) proxy 的具體應(yīng)用場(chǎng)景,具體的代碼放在 jsProxy 倉(cāng)庫(kù)中

從ES6重新認(rèn)識(shí)JavaScript設(shè)計(jì)模式(五): 代理模式和Proxy:本文從設(shè)計(jì)模式上去理解 Proxy 的應(yīng)用

使用 Javascript 原生的 Proxy 優(yōu)化應(yīng)用 :文章涉及到 Proxy 的基本用法、如何使用 Proxy 創(chuàng)建代理模式,以及如何對(duì)應(yīng)用進(jìn)行優(yōu)化。

手冊(cè)類

MDN - Proxy:MDN 上的 Proxy 官方文檔

MDN - Reflect:MDN 上的 Reflect 官方文檔

MDN - 元編程:MDN 官方文檔教程,介紹了元編程的概念,應(yīng)該算是比較抽象的,當(dāng)手冊(cè)翻翻不錯(cuò);

ECMAScript 6 入門 - Proxy:阮一峰翻譯的 《ECMAScript 6 入門》 教程

ES6 自定義JavaScript語(yǔ)言行為的 Proxy 對(duì)象:算是簡(jiǎn)明版的中文版的 API 手冊(cè)

在沒(méi)充分理解元編程之前翻手冊(cè)還是挺枯燥的,建議平時(shí)使用的時(shí)候再?gòu)倪@里補(bǔ)漏

隨著時(shí)間的推移,上面收集的文章可能會(huì)顯得陳舊,又有可能出現(xiàn)新的好文章,推薦在搜索引擎中使用 js Metaprogramming 或者 es6 proxy 進(jìn)行搜索相關(guān)文章;

3、代碼片段

下面摘抄一些代碼片段,方便自己后續(xù)在應(yīng)用 JS 元編程的時(shí)候快速 "借鑒"。你們?nèi)绻灿杏X(jué)得不錯(cuò)的代碼片段,歡迎在 issue 中回復(fù),我將不定期更新到這兒。

目錄

Schema 校驗(yàn)

自動(dòng)填充對(duì)象

進(jìn)制轉(zhuǎn)換

緩存代理

實(shí)現(xiàn)私有屬性

函數(shù)節(jié)流

圖片懶加載

監(jiān)聽(tīng)屬性更改

實(shí)現(xiàn)單例模式

Python 那樣截取數(shù)組

Schema 校驗(yàn) ↑
示例來(lái)自 ES6 Proxies in Depth

場(chǎng)景person 是一個(gè)普通對(duì)象,包含一個(gè) age 屬性,當(dāng)我們給它賦值的時(shí)候確保是大于零的數(shù)值,否則賦值失敗并拋出異常。

var person = { age: 27 };

思路:通過(guò)設(shè)置 set trap,其中包含了對(duì) age 字段的校驗(yàn)邏輯。

代碼

var validator = {
  set (target, key, value) {
    if (key === "age") {
      if (typeof value !== "number" || Number.isNaN(value)) {
        throw new TypeError("Age must be a number")
      }
      if (value <= 0) {
        throw new TypeError("Age must be a positive number")
      }
    }
    return true
  }
}
var proxy = new Proxy(person, validator)
proxy.age = "foo"
// <- TypeError: Age must be a number
proxy.age = NaN
// <- TypeError: Age must be a number
proxy.age = 0
// <- TypeError: Age must be a positive number
proxy.age = 28
console.log(person.age)
// <- 28

自動(dòng)填充對(duì)象 ↑
示例來(lái)自 深入淺出ES6(十二):代理 Proxies

場(chǎng)景:創(chuàng)建一個(gè)Tree()函數(shù)來(lái)實(shí)現(xiàn)以下特性,當(dāng)我們需要時(shí),所有中間對(duì)象 branch1、branch2branch3 都可以自動(dòng)創(chuàng)建。

var tree = Tree();
tree
//    { }
tree.branch1.branch2.twig = "green";
// { branch1: { branch2: { twig: "green" } } }

tree.branch1.branch3.twig = "yellow";

// { branch1: { branch2: { twig: "green" },
//                 branch3: { twig: "yellow" }}}

思路:Tree 返回的就是一個(gè) proxy 實(shí)例,通過(guò) get trap ,當(dāng)不存在屬性的時(shí)候自動(dòng)創(chuàng)建一個(gè)子樹(shù)。

代碼

  function Tree() {
    return new Proxy({}, handler);
  }
  var handler = {
    get: function (target, key, receiver) {
      if (!(key in target)) {
        target[key] = Tree();  // 自動(dòng)創(chuàng)建一個(gè)子樹(shù)
      }
      return Reflect.get(target, key, receiver);
    }
  };

進(jìn)制轉(zhuǎn)換 ↑
示例來(lái)自 深入淺出ES6(十二):代理 Proxies

場(chǎng)景:比如將 2 進(jìn)制轉(zhuǎn)換成 16 進(jìn)制或者 8 進(jìn)制,反之也能轉(zhuǎn)換。

思路:由于大部分的功能是相同的,我們通過(guò)函數(shù)名字將變量提取出來(lái),然后通過(guò) get trap 完成進(jìn)制轉(zhuǎn)換。

代碼

const baseConvertor = new Proxy({}, {
  get: function baseConvert(object, methodName) {
    var methodParts = methodName.match(/base(d+)toBase(d+)/);
    var fromBase = methodParts && methodParts[1];
    var toBase = methodParts && methodParts[2];
    if (!methodParts || fromBase > 36 || toBase > 36 || fromBase < 2 || toBase < 2) {
      throw new Error("TypeError: baseConvertor" + methodName + " is not a function");
    }
    return function (fromString) {
      return parseInt(fromString, fromBase).toString(toBase);
    }
  }
});

baseConvertor.base16toBase2("deadbeef") === "11011110101011011011111011101111";
baseConvertor.base2toBase16("11011110101011011011111011101111") === "deadbeef";

緩存代理 ↑
示例來(lái)自 從ES6重新認(rèn)識(shí)JavaScript設(shè)計(jì)模式(五): 代理模式和Proxy

場(chǎng)景:以沒(méi)有經(jīng)過(guò)任何優(yōu)化的計(jì)算斐波那契數(shù)列的函數(shù)來(lái)假設(shè)為開(kāi)銷很大的方法,這種遞歸調(diào)用在計(jì)算 40 以上的斐波那契項(xiàng)時(shí)就能明顯的感到延遲感。希望通過(guò)緩存來(lái)改善。

const getFib = (number) => {
  if (number <= 2) {
    return 1;
  } else {
    return getFib(number - 1) + getFib(number - 2);
  }
}
注:這只是演示緩存的寫(xiě)法,遞歸調(diào)用本身就有問(wèn)題,容易導(dǎo)致內(nèi)存泄露,在實(shí)際應(yīng)用中需要改寫(xiě)上述的 getFib 函數(shù)。

思路:因?yàn)槭呛瘮?shù)調(diào)用,所以需使用 apply trap,利用 Map 或者普通對(duì)象存儲(chǔ)每次計(jì)算的結(jié)果,在執(zhí)行運(yùn)算前先去 Map 查詢計(jì)算值是否被緩存。(相當(dāng)于以空間換時(shí)間,獲得性能提升)

代碼

const getCacheProxy = (fn, cache = new Map()) => {
  return new Proxy(fn, {
    apply(target, context, args) {
      const argsString = args.join(" ");
      if (cache.has(argsString)) {
        // 如果有緩存,直接返回緩存數(shù)據(jù)
        console.log(`輸出${args}的緩存結(jié)果: ${cache.get(argsString)}`);
        
        return cache.get(argsString);
      }
      const result = Reflect.apply(target, undefined, args);
      cache.set(argsString, result);

      return result;
    }
  })
}

const getFibProxy = getCacheProxy(getFib);
getFibProxy(40); // 102334155
getFibProxy(40); // 輸出40的緩存結(jié)果: 102334155

在實(shí)際應(yīng)用中數(shù)據(jù)量越大、計(jì)算過(guò)程越復(fù)雜,優(yōu)化效果越好,否則有可能會(huì)得不償失。

實(shí)現(xiàn)私有屬性 ↑
示例來(lái)自 從ES6重新認(rèn)識(shí)JavaScript設(shè)計(jì)模式(五): 代理模式和Proxy

場(chǎng)景:眾所周知,JavaScript是沒(méi)有私有屬性這一個(gè)概念的,私有屬性一般是以 _ 下劃線開(kāi)頭,請(qǐng)通過(guò) Proxy 限制以 _ 開(kāi)頭的屬性的訪問(wèn)。

const myObj = {
  public: "hello",
  _private: "secret",
  method: function () {
    console.log(this._private);
  }
},

思路:看上去比較簡(jiǎn)單,貌似使用 getset 這兩個(gè) trap 就可以,但實(shí)際上并不是。實(shí)際上還需要實(shí)現(xiàn) has, ownKeys , getOwnPropertyDescriptor 這些 trap,這樣就能最大限度的限制私有屬性的訪問(wèn)。

代碼

function getPrivateProps(obj, filterFunc) {
  return new Proxy(obj, {
    get(obj, prop) {
      if (!filterFunc(prop)) {
        let value = Reflect.get(obj, prop);
        // 如果是方法, 將this指向修改原對(duì)象
        if (typeof value === "function") {
          value = value.bind(obj);
        }
        return value;
      }
    },
    set(obj, prop, value) {
      if (filterFunc(prop)) {
        throw new TypeError(`Can"t set property "${prop}"`);
      }
      return Reflect.set(obj, prop, value);
    },
    has(obj, prop) {
      return filterFunc(prop) ? false : Reflect.has(obj, prop);
    },
    ownKeys(obj) {
      return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
    },
    getOwnPropertyDescriptor(obj, prop) {
      return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
    }
  });
}

function propFilter(prop) {
  return prop.indexOf("_") === 0;
}

myProxy = getPrivateProps(myObj, propFilter);

console.log(JSON.stringify(myProxy)); // {"public":"hello"}
console.log(myProxy._private); // undefined
console.log("_private" in myProxy); // false
console.log(Object.keys(myProxy)); // ["public", "method"]
for (let prop in myProxy) { console.log(prop); }    // public  method
myProxy._private = 1; // Uncaught TypeError: Can"t set property "_private"

注意:其中在 get 方法的內(nèi)部,我們有個(gè)判斷,如果訪問(wèn)的是對(duì)象方法使將 this 指向被代理對(duì)象,這是在使用 Proxy 需要十分注意的,如果不這么做方法內(nèi)部的 this 會(huì)指向 Proxy 代理。

一般來(lái)講,set trap 都會(huì)默認(rèn)觸發(fā) getOwnPropertyDescriptordefineProperty

函數(shù)節(jié)流 ↑
示例來(lái)自 使用 Javascript 原生的 Proxy 優(yōu)化應(yīng)用

場(chǎng)景:控制函數(shù)調(diào)用的頻率.

const handler = () => console.log("Do something...");
document.addEventListener("scroll", handler);

思路:涉及到函數(shù)的調(diào)用,所以使用 apply trap 即可。

代碼

const createThrottleProxy = (fn, rate) => {
  let lastClick = Date.now() - rate;
  return new Proxy(fn, {
    apply(target, context, args) {
      if (Date.now() - lastClick >= rate) {
        fn.bind(target)(args);
        lastClick = Date.now();
      }
    }
  });
};

const handler = () => console.log("Do something...");
const handlerProxy = createThrottleProxy(handler, 1000);
document.addEventListener("scroll", handlerProxy);

同樣需要注意使用 bind 綁定上下文,不過(guò)這里的示例使用了箭頭函數(shù),不用 bind 也沒(méi)啥問(wèn)題。

圖片懶加載 ↑
示例來(lái)自 使用 Javascript 原生的 Proxy 優(yōu)化應(yīng)用

場(chǎng)景:為了更好的用戶體驗(yàn),在加載圖片的時(shí)候,使用 loading 占位圖,等真正圖片加載完畢之后再顯示出來(lái)。原始的寫(xiě)法如下:

const img = new Image();
img.src = "/some/big/size/image.jpg";
document.body.appendChild(img);

思路:加載圖片的時(shí)候,會(huì)讀取 img.src 屬性,我們使用 constructor trap 控制在創(chuàng)建的時(shí)候默認(rèn)使用 loading 圖,等加載完畢再將真實(shí)地址賦給 img;

代碼

 const IMG_LOAD = "https://img.alicdn.com/tfs/TB11rDdclLoK1RjSZFuXXXn0XXa-300-300.png";

  const imageProxy = (loadingImg) => {
      return new Proxy(Image, {
          construct(target, args){
              const instance = Reflect.construct(target, args);
              instance.src = loadingImg;
              return instance;
          }
      });
  };

  const ImageProxy = imageProxy(IMG_LOAD);

  const createImageProxy = (realImg) =>{
      const img = new ImageProxy();
      const virtualImg = new Image();
      virtualImg.src = realImg;
      virtualImg.onload = () => {
          hasLoaded = true;
          img.src = realImg;
      };
      return img;
  }
  var img = createImageProxy("https://cdn.dribbble.com/users/329207/screenshots/5289734/bemocs_db_dribbble_03_gold_leaf.jpg");
  document.body.appendChild(img);

監(jiān)聽(tīng)屬性更改 ↑
示例來(lái)自 ES6 Features - 10 Use Cases for Proxy

場(chǎng)景:當(dāng)普通對(duì)象屬性更改后,觸發(fā)所綁定的 onChange 回調(diào);

思路:能更改屬性的有 setdeleteProperty 這兩個(gè) trap,在其中調(diào)用 onChange 方法即可

function trackChange(obj, onChange) {
    const handler = {
        set (obj, prop, value) {
            const oldVal = obj[prop];
            Reflect.set(obj, prop, value);
            onChange(obj, prop, oldVal, value);
        },
        deleteProperty (obj, prop) {
            const oldVal = obj[prop];
            Reflect.deleteProperty(obj, prop);
            onChange(obj, prop, oldVal, undefined);
        }
    };
    return new Proxy(obj, handler);
}

// 應(yīng)用在對(duì)象上
let myObj = trackChange({a: 1, b: 2}, function (obj, prop, oldVal, newVal) {
    console.log(`myObj.${prop} changed from ${oldVal} to ${newVal}`);
});

myObj.a = 5;     // myObj.a changed from 1 to 5
delete myObj.b;  // myObj.b changed from 2 to undefined
myObj.c = 6;     // myObj.c changed from undefined to 6

// 應(yīng)用在數(shù)組上
let myArr = trackChange([1,2,3], function (obj, prop, oldVal, newVal) {
    let propFormat = isNaN(parseInt(prop)) ? `.${prop}` : `[${prop}]`,
        arraySum = myArr.reduce((a,b) => a + b);
    console.log(`myArr${propFormat} changed from ${oldVal} to ${newVal}`);
    console.log(`  sum [${myArr}] = ${arraySum}`);
});

myArr[0] = 4;      // myArr[0] changed from 1 to 4         
                   //   sum [4,2,3] = 9
delete myArr[2];   // myArr[2] changed from 3 to undefined                
                   //   sum [4,2,] = 6
myArr.length = 1;  // myArr.length changed from 3 to 1                
                   //   sum [4] = 4

實(shí)現(xiàn)單例模式 ↑
示例來(lái)自 ES6 Features - 10 Use Cases for Proxy

場(chǎng)景:實(shí)現(xiàn)單例設(shè)計(jì)模式;

思路:和創(chuàng)建有關(guān)的,是 construct 這個(gè) trap,每次我們返回相同的實(shí)例即可。

代碼

// makes a singleton proxy for a constructor function
function makeSingleton(func) {
    let instance,
        handler = {
            construct: function (target, args) {
                if (!instance) {
                    instance = new func();
                }
                return instance;
            }
        };
    return new Proxy(func, handler);
}


// 以這個(gè)為 constructor 為例
function Test() {
    this.value = 0;
}

// 普通創(chuàng)建實(shí)例
const t1 = new Test(),
    t2 = new Test();
t1.value = 123;
console.log("Normal:", t2.value);  // 0 - 因?yàn)?t1、t2 是不同的實(shí)例

// 使用 Proxy 來(lái) trap 構(gòu)造函數(shù), 完成單例模式
const TestSingleton = makeSingleton(Test),
    s1 = new TestSingleton(),
    s2 = new TestSingleton();
s1.value = 123;
console.log("Singleton:", s2.value);  // 123 - 現(xiàn)在 s1、s2 是相同的實(shí)例。

像 Python 那樣截取數(shù)組 ↑
示例來(lái)自 ES6 Features - 10 Use Cases for Proxy

場(chǎng)景:在 python 中,你可以使用 list[10:20:3] 來(lái)獲取 10 到 20 索性中每隔 3 個(gè)的元素組成的數(shù)組(也支持負(fù)數(shù)索引)。

思路:由于在 JS 中,數(shù)組方括號(hào)語(yǔ)法中不支持冒號(hào),只能曲線救國(guó),使用這樣 list["10:20:3"] 的形式。只需要實(shí)現(xiàn) get trap 即可。

// Python-like array slicing

function pythonIndex(array) {

    function parse(value, defaultValue, resolveNegative) {
        if (value === undefined || isNaN(value)) {
            value = defaultValue;
        } else if (resolveNegative && value < 0) {
            value += array.length;
        }
        return value;
    }
    
    function slice(prop) {
        if (typeof prop === "string" && prop.match(/^[+-d:]+$/)) {
            // no ":", return a single item
            if (prop.indexOf(":") === -1) {
                let index = parse(parseInt(prop, 10), 0, true);
                console.log(prop, "		", array[index]);
                return array[index];
            }                
            // otherwise: parse the slice string
            let [start, end, step] = prop.split(":").map(part => parseInt(part, 10));
            step = parse(step, 1, false);
            if (step === 0) {
                throw new RangeError("Step can"t be zero");
            }
            if (step > 0) {
                start = parse(start, 0, true);
                end = parse(end, array.length, true);
            } else {
                start = parse(start, array.length - 1, true);
                end = parse(end, -1, true);
            }
            // slicing
            let result = [];
            for (let i = start; start <= end ? i < end : i > end; i += step) {
                result.push(array[i]);
            }
            console.log(prop, "	", JSON.stringify(result));
            return result;
        }
    }

    const handler = {
        get (arr, prop) {
            return slice(prop) || Reflect.get(array, prop);
        }
    };
    return new Proxy(array, handler);
}


// try it out
let values = [0,1,2,3,4,5,6,7,8,9],
    pyValues = pythonIndex(values);

console.log(JSON.stringify(values));

pyValues["-1"];      // 9
pyValues["0:3"];     // [0,1,2]    
pyValues["8:5:-1"];  // [8,7,6]
pyValues["-8::-1"];  // [2,1,0]
pyValues["::-1"];    // [9,8,7,6,5,4,3,2,1,0]
pyValues["4::2"];    // [4,6,8]

// 不影響正常的索引
pyValues[3];         // 3
小結(jié)

本文總結(jié)了自己學(xué)習(xí) ES6 元編程相關(guān)知識(shí)(Symbols & Proxy & Reflect)的理解、教程文檔 和 代碼片段。

由于教程文檔和代碼片段將隨著學(xué)習(xí)的進(jìn)行將增多,所以后續(xù)還會(huì)不定期更新。如果你也有好的資源,歡迎到 issue 中回復(fù)共享。

Changelog

2018.09.22 更新 圖片懶加載 代碼片段,改用 construct trap 實(shí)現(xiàn);更新原因:bugfix,原來(lái)的代碼所創(chuàng)建的 img 是 proxy 對(duì)象,執(zhí)行 document.body.appendChild(img) 將報(bào)錯(cuò)。

下面的是我的公眾號(hào)二維碼圖片,歡迎關(guān)注。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97011.html

相關(guān)文章

  • ES6Proxy &amp; Reflection API

    摘要:的出現(xiàn),使用內(nèi)建對(duì)象的繼承得以實(shí)現(xiàn)。屬性不存在拋出異常是取值操作,而就是賦值操作,可以對(duì)屬性值進(jìn)行驗(yàn)證。屬性必須為數(shù)字拋出異常接受兩個(gè)參數(shù)被讀取屬性的原對(duì)象,即代理的目標(biāo)。這個(gè)可以攔截內(nèi)部方法,通過(guò)返回?cái)?shù)組的值可以覆寫(xiě)其行為。 Proxy & Reflect extends的出現(xiàn),使用內(nèi)建對(duì)象的繼承得以實(shí)現(xiàn)。Proxy可以攔截JS引擎內(nèi)部目標(biāo)的底層對(duì)象操作,這些底層操作被攔截后會(huì)觸發(fā)響...

    yearsj 評(píng)論0 收藏0
  • Set &amp; Map:新生的數(shù)據(jù)集合及其弱引用衍生

    摘要:前言新增了兩種基本的原生數(shù)據(jù)集合和加上和現(xiàn)在共有四種,以及由兩者衍生出的弱引用集合和。其本身是生成實(shí)例數(shù)據(jù)集合的構(gòu)造函數(shù),可以接受一個(gè)數(shù)組或具有接口的數(shù)據(jù)結(jié)構(gòu)作為參數(shù)用來(lái)初始化。返回鍵值對(duì)的遍歷器對(duì)象,鍵值對(duì)為鍵名鍵值。 前言 ES6新增了兩種基本的原生數(shù)據(jù)集合:Set和Map(加上Array和Object現(xiàn)在共有四種),以及由兩者衍生出的弱引用集合:WeakSet和WeakMap。從...

    AprilJ 評(píng)論0 收藏0
  • 重溫ES6核心概念和基本用法

    摘要:凡是部署了屬性的數(shù)據(jù)結(jié)構(gòu),就稱為部署了遍歷器接口。調(diào)用這個(gè)接口,就會(huì)返回一個(gè)遍歷器對(duì)象。 ES6在2015年6月就得以批準(zhǔn),至今已兩年了。近一年多以來(lái)陸續(xù)看過(guò)很多ES6的資料,工作項(xiàng)目中也逐步的用上了很多ES6的特性(let,const,promise,Template strings,Class,箭頭函數(shù)等等),不得不說(shuō),這些特性給開(kāi)發(fā)帶來(lái)了非常多的便利。但是做決定我的ES6知識(shí)其...

    philadelphia 評(píng)論0 收藏0
  • ES6簡(jiǎn)單總結(jié)(搭配簡(jiǎn)單的講解和小案例)

    摘要:方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值,與字符串的方法類似。不可以當(dāng)作構(gòu)造函數(shù),也就是說(shuō),不可以使用命令,否則會(huì)拋出一個(gè)錯(cuò)誤。本身是一個(gè)構(gòu)造函數(shù),用來(lái)生成數(shù)據(jù)結(jié)構(gòu)。返回一個(gè)布爾值,表示該值是否為的成員。清除所有成員,沒(méi)有返回值。 在學(xué)習(xí)es6的過(guò)程中,為了方便自己復(fù)習(xí),以及查看,對(duì)api做了一個(gè)極簡(jiǎn)用例介紹。如有錯(cuò)誤多多指正。 一 let和const 1.let (1)一個(gè)大...

    joyqi 評(píng)論0 收藏0
  • ECMAScript6

    摘要:返回布爾值標(biāo)簽?zāi)0蹇梢跃o跟一個(gè)函數(shù)名后邊,該函數(shù)將被調(diào)用來(lái)處理這個(gè)模板字符串。其它情況下返回值為在內(nèi)部,整數(shù)和浮點(diǎn)數(shù)使用同樣的存儲(chǔ)方法,所以和被視為同一個(gè)值。 簡(jiǎn)介 ES6目標(biāo),讓JavaScript變成一個(gè)企業(yè)級(jí)的開(kāi)發(fā)語(yǔ)言,不僅僅限制與前端頁(yè)面的腳本語(yǔ)言。 標(biāo)準(zhǔn)(Standard): 用于定義與其他事物區(qū)別的一套規(guī)則 實(shí)現(xiàn)(Implementation): 某個(gè)標(biāo)準(zhǔn)的具體實(shí)施/真實(shí)實(shí)...

    MSchumi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

aikin

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<