国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

ES6基礎(chǔ)知識(shí)八:你是怎么理解ES6中Proxy的?使用場(chǎng)景?

這篇具有很好參考價(jià)值的文章主要介紹了ES6基礎(chǔ)知識(shí)八:你是怎么理解ES6中Proxy的?使用場(chǎng)景?。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

ES6基礎(chǔ)知識(shí)八:你是怎么理解ES6中Proxy的?使用場(chǎng)景?,es6,es6,前端,ecmascript
一、介紹

定義: 用于定義基本操作的自定義行為

本質(zhì): 修改的是程序默認(rèn)形為,就形同于在編程語(yǔ)言層面上做修改,屬于元編程(meta programming)

元編程(Metaprogramming,又譯超編程,是指某類計(jì)算機(jī)程序的編寫,這類計(jì)算機(jī)程序編寫或者操縱其它程序(或者自身)作為它們的數(shù)據(jù),或者在運(yùn)行時(shí)完成部分本應(yīng)在編譯時(shí)完成的工作

一段代碼來(lái)理解

#!/bin/bash
# metaprogram
echo '#!/bin/bash' >program
for ((I=1; I<=1024; I++)) do
    echo "echo $I" >>program
done
chmod +x program

這段程序每執(zhí)行一次能幫我們生成一個(gè)名為program的文件,文件內(nèi)容為1024行echo,如果我們手動(dòng)來(lái)寫1024行代碼,效率顯然低效

元編程優(yōu)點(diǎn):與手工編寫全部代碼相比,程序員可以獲得更高的工作效率,或者給與程序更大的靈活度去處理新的情形而無(wú)需重新編譯

Proxy 亦是如此,用于創(chuàng)建一個(gè)對(duì)象的代理,從而實(shí)現(xiàn)基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數(shù)調(diào)用等)

二、用法

Proxy為 構(gòu)造函數(shù),用來(lái)生成 Proxy實(shí)例

var proxy = new Proxy(target, handler)

參數(shù)

  • target表示所要攔截的目標(biāo)對(duì)象(任何類型的對(duì)象,包括原生數(shù)組,函數(shù),甚至另一個(gè)代理))
  • handler通常以函數(shù)作為屬性的對(duì)象,各屬性中的函數(shù)分別定義了在執(zhí)行各種操作時(shí)代理 p 的行為

handler解析

關(guān)于handler攔截屬性,有如下:

  • get(target,propKey,receiver):攔截對(duì)象屬性的讀取
  • set(target,propKey,value,receiver):攔截對(duì)象屬性的設(shè)置
  • has(target,propKey):攔截propKey in proxy的操作,返回一個(gè)布爾值
  • deleteProperty(target,propKey):攔截delete proxy[propKey]的操作,返回一個(gè)布爾值
  • ownKeys(target):攔截Object.keys(proxy)、for…in等循環(huán),返回一個(gè)數(shù)組
  • getOwnPropertyDescriptor(target, propKey):攔截Object.getOwnPropertyDescriptor(proxy, propKey),返回屬性的描述對(duì)象
  • defineProperty(target, propKey, propDesc):攔截Object.defineProperty(proxy, propKey, propDesc),返回一個(gè)布爾值
  • preventExtensions(target):攔截Object.preventExtensions(proxy),返回一個(gè)布爾值
  • getPrototypeOf(target):攔截Object.getPrototypeOf(proxy),返回一個(gè)對(duì)象
  • isExtensible(target):攔截Object.isExtensible(proxy),返回一個(gè)布爾值
  • setPrototypeOf(target, proto):攔截Object.setPrototypeOf(proxy, proto),返回一個(gè)布爾值
  • apply(target, object, args):攔截 Proxy 實(shí)例作為函數(shù)調(diào)用的操作
  • construct(target, args):攔截 Proxy 實(shí)例作為構(gòu)造函數(shù)調(diào)用的操作

Reflect

若需要在Proxy內(nèi)部調(diào)用對(duì)象的默認(rèn)行為,建議使用Reflect,其是ES6中操作對(duì)象而提供的新 API

基本特點(diǎn):

  • 只要Proxy對(duì)象具有的代理方法,Reflect對(duì)象全部具有,以靜態(tài)方法的形式存在
  • 修改某些Object方法的返回結(jié)果,讓其變得更合理(定義不存在屬性行為的時(shí)候不報(bào)錯(cuò)而是返回false)
  • 讓Object操作都變成函數(shù)行為

下面我們介紹proxy幾種用法:

get()

get接受三個(gè)參數(shù),依次為目標(biāo)對(duì)象、屬性名和 proxy 實(shí)例本身,最后一個(gè)參數(shù)可選

var person = {
  name: "張三"
};

var proxy = new Proxy(person, {
  get: function(target, propKey) {
    return Reflect.get(target,propKey)
  }
});

proxy.name // "張三"

get能夠?qū)?shù)組增刪改查進(jìn)行攔截,下面是試下你數(shù)組讀取負(fù)數(shù)的索引

function createArray(...elements) {
  let handler = {
    get(target, propKey, receiver) {
      let index = Number(propKey);
      if (index < 0) {
        propKey = String(target.length + index);
      }
      return Reflect.get(target, propKey, receiver);
    }
  };

  let target = [];
  target.push(...elements);
  return new Proxy(target, handler);
}

let arr = createArray('a', 'b', 'c');
arr[-1] // c

注意:如果一個(gè)屬性不可配置(configurable)且不可寫(writable),則 Proxy 不能修改該屬性,否則會(huì)報(bào)錯(cuò)

const target = Object.defineProperties({}, {
  foo: {
    value: 123,
    writable: false,
    configurable: false
  },
});

const handler = {
  get(target, propKey) {
    return 'abc';
  }
};

const proxy = new Proxy(target, handler);

proxy.foo
// TypeError: Invariant check failed

set()

set方法用來(lái)攔截某個(gè)屬性的賦值操作,可以接受四個(gè)參數(shù),依次為目標(biāo)對(duì)象、屬性名、屬性值和 Proxy 實(shí)例本身

假定Person對(duì)象有一個(gè)age屬性,該屬性應(yīng)該是一個(gè)不大于 200 的整數(shù),那么可以使用Proxy保證age的屬性值符合要求

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');
      }
    }

    // 對(duì)于滿足條件的 age 屬性以及其他屬性,直接保存
    obj[prop] = value;
  }
};

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

person.age = 100;

person.age // 100
person.age = 'young' // 報(bào)錯(cuò)
person.age = 300 // 報(bào)錯(cuò)

如果目標(biāo)對(duì)象自身的某個(gè)屬性,不可寫且不可配置,那么set方法將不起作用

const obj = {};
Object.defineProperty(obj, 'foo', {
  value: 'bar',
  writable: false,
});

const handler = {
  set: function(obj, prop, value, receiver) {
    obj[prop] = 'baz';
  }
};

const proxy = new Proxy(obj, handler);
proxy.foo = 'baz';
proxy.foo // "bar"

注意,嚴(yán)格模式下,set代理如果沒(méi)有返回true,就會(huì)報(bào)錯(cuò)

'use strict';
const handler = {
  set: function(obj, prop, value, receiver) {
    obj[prop] = receiver;
    // 無(wú)論有沒(méi)有下面這一行,都會(huì)報(bào)錯(cuò)
    return false;
  }
};
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
// TypeError: 'set' on proxy: trap returned falsish for property 'foo'

deleteProperty()

deleteProperty方法用于攔截delete操作,如果這個(gè)方法拋出錯(cuò)誤或者返回false,當(dāng)前屬性就無(wú)法被delete命令刪除

var handler = {
  deleteProperty (target, key) {
    invariant(key, 'delete');
    Reflect.deleteProperty(target,key)
    return true;
  }
};
function invariant (key, action) {
  if (key[0] === '_') {
    throw new Error(`無(wú)法刪除私有屬性`);
  }
}

var target = { _prop: 'foo' };
var proxy = new Proxy(target, handler);
delete proxy._prop
// Error: 無(wú)法刪除私有屬性

注意,目標(biāo)對(duì)象自身的不可配置(configurable)的屬性,不能被deleteProperty方法刪除,否則報(bào)錯(cuò)

取消代理

Proxy.revocable(target, handler);

三、使用場(chǎng)景

Proxy其功能非常類似于設(shè)計(jì)模式中的代理模式,常用功能如下:

  • 攔截和監(jiān)視外部對(duì)對(duì)象的訪問(wèn)
  • 降低函數(shù)或類的復(fù)雜度
  • 在復(fù)雜操作前對(duì)操作進(jìn)行校驗(yàn)或?qū)λ栀Y源進(jìn)行管理

使用 Proxy 保障數(shù)據(jù)類型的準(zhǔn)確性

let numericDataStore = { count: 0, amount: 1234, total: 14 };
numericDataStore = new Proxy(numericDataStore, {
    set(target, key, value, proxy) {
        if (typeof value !== 'number') {
            throw Error("屬性只能是number類型");
        }
        return Reflect.set(target, key, value, proxy);
    }
});

numericDataStore.count = "foo"
// Error: 屬性只能是number類型

numericDataStore.count = 333
// 賦值成功

聲明了一個(gè)私有的 apiKey,便于 api 這個(gè)對(duì)象內(nèi)部的方法調(diào)用,但不希望從外部也能夠訪問(wèn) api._apiKey

let api = {
    _apiKey: '123abc456def',
    getUsers: function(){ },
    getUser: function(userId){ },
    setUser: function(userId, config){ }
};
const RESTRICTED = ['_apiKey'];
api = new Proxy(api, {
    get(target, key, proxy) {
        if(RESTRICTED.indexOf(key) > -1) {
            throw Error(`${key} 不可訪問(wèn).`);
        } return Reflect.get(target, key, proxy);
    },
    set(target, key, value, proxy) {
        if(RESTRICTED.indexOf(key) > -1) {
            throw Error(`${key} 不可修改`);
        } return Reflect.get(target, key, value, proxy);
    }
});

console.log(api._apiKey)
api._apiKey = '987654321'
// 上述都拋出錯(cuò)誤

還能通過(guò)使用Proxy實(shí)現(xiàn)觀察者模式

觀察者模式(Observer mode)指的是函數(shù)自動(dòng)觀察數(shù)據(jù)對(duì)象,一旦對(duì)象有變化,函數(shù)就會(huì)自動(dòng)執(zhí)行

observable函數(shù)返回一個(gè)原始對(duì)象的 Proxy 代理,攔截賦值操作,觸發(fā)充當(dāng)觀察者的各個(gè)函數(shù)

const queuedObservers = new Set();

const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});

function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  queuedObservers.forEach(observer => observer());
  return result;
}

觀察者函數(shù)都放進(jìn)Set集合,當(dāng)修改obj的值,在會(huì)set函數(shù)中攔截,自動(dòng)執(zhí)行Set所有的觀察者文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-608251.html

到了這里,關(guān)于ES6基礎(chǔ)知識(shí)八:你是怎么理解ES6中Proxy的?使用場(chǎng)景?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 你是怎么理解ES6中 Decorator 的?使用場(chǎng)景?

    你是怎么理解ES6中 Decorator 的?使用場(chǎng)景?

    Decorator,即裝飾器,從名字上很容易讓我們聯(lián)想到裝飾者模式 簡(jiǎn)單來(lái)講,裝飾者模式就是一種在不改變?cè)惡褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展對(duì)象功能的設(shè)計(jì)理論。 ES6 中 Decorator 功能亦如此,其本質(zhì)也不是什么高大上的結(jié)構(gòu),就是一個(gè)普通的函數(shù),用于擴(kuò)展類屬性和類方法

    2024年03月11日
    瀏覽(24)
  • 你是怎么理解ES6中 Promise的?使用場(chǎng)景?

    你是怎么理解ES6中 Promise的?使用場(chǎng)景?

    Promise ,譯為承諾,是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù))更加合理和更加強(qiáng)大 在以往我們?nèi)绻幚矶鄬赢惒讲僮?,我們往往?huì)像下面那樣編寫我們的代碼 閱讀上面代碼,是不是很難受,上述形成了經(jīng)典的回調(diào)地獄 現(xiàn)在通過(guò) Promise 的改寫上面的代碼 瞬

    2024年03月15日
    瀏覽(23)
  • 你是怎么理解ES6中Module的?使用場(chǎng)景?

    你是怎么理解ES6中Module的?使用場(chǎng)景?

    模塊,(Module),是能夠單獨(dú)命名并獨(dú)立地完成一定功能的程序語(yǔ)句的集合(即程序代碼和數(shù)據(jù)結(jié)構(gòu)的集合體)。 兩個(gè)基本的特征:外部特征和內(nèi)部特征 外部特征是指模塊跟外部環(huán)境聯(lián)系的接口(即其他模塊或程序調(diào)用該模塊的方式,包括有輸入輸出參數(shù)、引用的全局變量

    2024年03月12日
    瀏覽(25)
  • 你是怎么理解ES6中 Generator的?使用場(chǎng)景?

    你是怎么理解ES6中 Generator的?使用場(chǎng)景?

    Generator 函數(shù)是 ES6 提供的一種異步編程解決方案,語(yǔ)法行為與傳統(tǒng)函數(shù)完全不同 回顧下上文提到的解決異步的手段: 回調(diào)函數(shù) promise 那么,上文我們提到 promsie 已經(jīng)是一種比較流行的解決異步方案,那么為什么還出現(xiàn) Generator ?甚至 async/await 呢? 該問(wèn)題我們留在后面再進(jìn)行

    2024年03月14日
    瀏覽(27)
  • ES6基礎(chǔ)知識(shí)二:ES6中數(shù)組新增了哪些擴(kuò)展?

    ES6基礎(chǔ)知識(shí)二:ES6中數(shù)組新增了哪些擴(kuò)展?

    一、擴(kuò)展運(yùn)算符的應(yīng)用 ES6通過(guò)擴(kuò)展元素符…,好比 rest 參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列 主要用于函數(shù)調(diào)用的時(shí)候,將一個(gè)數(shù)組變?yōu)閰?shù)序列 可以將某些數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為數(shù)組 能夠更簡(jiǎn)單實(shí)現(xiàn)數(shù)組復(fù)制 const a1 = [1, 2]; const […a2] = a1; // [1,2] 數(shù)組的合并也更為

    2024年02月16日
    瀏覽(25)
  • ES6基礎(chǔ)知識(shí)三:對(duì)象新增了哪些擴(kuò)展?

    ES6基礎(chǔ)知識(shí)三:對(duì)象新增了哪些擴(kuò)展?

    一、屬性的簡(jiǎn)寫 ES6中,當(dāng)對(duì)象鍵名與對(duì)應(yīng)值名相等的時(shí)候,可以進(jìn)行簡(jiǎn)寫 方法也能夠進(jìn)行簡(jiǎn)寫 在函數(shù)內(nèi)作為返回值,也會(huì)變得方便很多 注意:簡(jiǎn)寫的對(duì)象方法不能用作構(gòu)造函數(shù),否則會(huì)報(bào)錯(cuò) 二、屬性名表達(dá)式 ES6 允許字面量定義對(duì)象時(shí),將表達(dá)式放在括號(hào)內(nèi) 表達(dá)式還可以

    2024年02月15日
    瀏覽(25)
  • JS 怎么理解ES6新增Set、Map兩種數(shù)據(jù)結(jié)構(gòu)?

    JS 怎么理解ES6新增Set、Map兩種數(shù)據(jù)結(jié)構(gòu)?

    目錄 一、前言 二、Set 1.Set數(shù)據(jù)結(jié)構(gòu)定義 2.Set數(shù)據(jù)結(jié)構(gòu)的特性 3.Set數(shù)據(jù)結(jié)構(gòu)的基本使用 4.Set遍歷數(shù)據(jù) 5.Set 的使用場(chǎng)景 6.WeakSet的使用 7.垃圾回收機(jī)制 三、Map 1.Map數(shù)據(jù)結(jié)構(gòu)定義 2.Map數(shù)據(jù)結(jié)構(gòu)的特性 3.Map數(shù)據(jù)結(jié)構(gòu)的基本使用 ?4.Map遍歷數(shù)據(jù) 5.Map的使用場(chǎng)景 6.WeakMap的使用 7.垃圾回收

    2024年02月08日
    瀏覽(27)
  • 【ES6】阮一峰ES6學(xué)習(xí)(六) Proxy

    【ES6】阮一峰ES6學(xué)習(xí)(六) Proxy

    es6 中全新設(shè)計(jì)了一個(gè)叫 Proxy 的類型, Proxy 這個(gè)詞的原意是代理,用在這里表示由它來(lái)”代理“某些操作,可以譯為”代理器“,可以這樣理解: 在目標(biāo)對(duì)象之前架設(shè)一層\\\"攔截\\\",外界對(duì)該對(duì)象的訪問(wèn),都必須先通過(guò)這層攔截 。 舉個(gè)簡(jiǎn)單的例子 比如茅臺(tái)酒的代理,有了這個(gè)

    2023年04月16日
    瀏覽(20)
  • 音視頻基礎(chǔ)知識(shí)——素材理解

    音視頻基礎(chǔ)知識(shí)——素材理解

    素材是媒體內(nèi)容生產(chǎn)中一切生產(chǎn)資料的集合,包括不限于視頻、音頻、圖片、字幕等形式。 素材通過(guò)統(tǒng)一的協(xié)議把原始的數(shù)據(jù)有序組織起來(lái),便于編輯與管理。比如一般的素材是由一個(gè)物理文件及其各類屬性構(gòu)成,在對(duì)素材進(jìn)行剪輯處理時(shí),不用改變?cè)次募械娜魏蝺?nèi)容,通

    2024年02月01日
    瀏覽(29)
  • OpenGL 和 OpenGL ES基礎(chǔ)知識(shí)

    當(dāng)今許多視覺(jué)應(yīng)用程序,從簡(jiǎn)單的游戲到高級(jí)工程領(lǐng)域,都使用OpenGL(Open Graphics Library)和OpenGL ES(OpenGL for Embedded Systems)作為其圖形渲染API。這些API提供了一種跨平臺(tái)、可移植且高性能的圖形編程解決方案,支持大量不同類型的設(shè)備和操作系統(tǒng)。 在本篇博客中,我們將深入

    2024年02月08日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包