目錄
前言
什么是代理?
什么是 JavaScript 代理?
初识代理:Hello World
小试牛刀:不要停止我的音乐
释放魔法:封装全宇宙所有 RESTful API
终极魔幻:通读代理人的魔法秘笈
首頁 web前端 js教程 JavaScript代理是什麼? javascript代理的介紹

JavaScript代理是什麼? javascript代理的介紹

Sep 21, 2018 am 10:53 AM
api javascript 前端 封裝 重構

本篇文章给大家带来的内容是关于JavaScript代理是什么?javascript代理的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

前言

什么是代理?

上小学的时候,李小红来你家叫你出去玩,第一个回应的不是你自己,是你妈:“王小明在家写作业,今天不出去!”

上中学的时候,赵二虎带着小弟们放学在校门口等着揍你,走在前面的不是你自己,是二虎他爸:“考试没及格还学会装黑社会了!”拎起二虎就是一顿胖揍。

上了大学,躺在宿舍里的床上,好饿。出门买饭并交代好不要葱蒜多放辣最后还直接端到床上的不是你自己,是快递小哥。

这些都是代理。

什么是 JavaScript 代理?

用官方的洋文来说,是 Proxy:

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

通过 Proxy 我们可以拦截并改变一个对象的几乎所有的根本操作,包括但不限于属性查找、赋值、枚举、函数调用等等。

在生活中,通过代理我们可以自动屏蔽小红的邀请、自动赶走二虎的威胁、自动买好干净的饭端到床上。在 JavaScript 世界里,代理也可以帮你做类似的事情,接下来让我们一起琢磨一番。

初识代理:Hello World

以小学经历为例子,心里是喜欢小红的,于是我们定义:

const me = { name: '小明', like: '小红' }
登入後複製

这个时候如果调用 console.log(me.like),结果必然是 小红。然而生活并不是这样,作为一个未成年人,总是有各种的代理人围绕在你身边,比如这样:

const meWithProxy = new Proxy(me, {
  get(target, prop) {
    if (prop === 'like') {
      return '学习';
    }
    return target[prop];
  }
});
登入後複製

这个时候如果调用 console.log(me.like) 依然是 小红 ,因为真心不会说谎。但当我们调用 console.log(meWithProxy.like) 的时候,就会可耻的输出 学习 ,告诉大家说我们喜欢的是 学习

小试牛刀:不要停止我的音乐

刚才我们简单了解了代理能够拦截对象属性的获取,可以隐藏真实的属性值而返回代理想要返回的结果,那么对于对象属性的赋值呢?让我们一起来看看。

假设你正在听音乐:

const me = { name: '小明', musicPlaying: true }
登入後複製

此时如果我们执行 me.musicPlaying = false 这样就轻而易举地停止了你的音乐,那么如果我们挂上代理人:

const meWithProxy = new Proxy(me, {
  set(target, prop, value) {
    if (prop === 'musicPlaying' && value !== true) {
      throw Error('任何妄图停止音乐的行为都是耍流氓!');
    }
    target[prop] = value;
  }
});
登入後複製

这时候如果我们执行 me.musicPlaying = false,就会被毫不留情地掀了桌子:

> meWithProxy.musicPlaying = false
Error: 任何妄图停止音乐的行为都是耍流氓!
    at Object.set (repl:4:13)
>
登入後複製

释放魔法:封装全宇宙所有 RESTful API

现在我们已经知道通过 Proxy 可以拦截属性的读写操作,那然后呢?没什么用?

仅仅是拦截属性的读写操作,的确没有太大的发挥空间,或许可以方便的做一些属性赋值校验工作等等。但是,或许你还没有意识到一个惊人的秘密:Proxy 在拦截属性读写操作时,并不在乎属性是否真的存在!

那么,也就是说:利用 Proxy,我们可以拦截并不存在的属性的读取。

再进一步思考:利用 Proxy,我们可以在属性读取的那一瞬间,动态构造返回结果。

然而,属性并不局限于字符串、布尔值,属性可以是对象、函数、任何东西。

至此,你想到了什么?

没想到?不要紧!根据刚才的分析,让我们一起通过下面 17 行代码,来封装全宇宙所有的 RESTful API !

import axios from 'axios';
const api = new Proxy({}, {
  get(target, prop) {
    const method = /^[a-z]+/.exec(prop)[0];
    const path = '/' + prop
          .substring(method.length)
          .replace(/([a-z])([A-Z])/g, '$1/$2')
          .replace(/\$/g, '/$/')
          .toLowerCase();
    return (...args) => { // <------ 返回动态构造的函数!
      const url = path.replace(/\$/g, () => args.shift());
      const options = args.shift() || {};
      console.log('Requesting: ', method, url, options);
      return axios({ method, url,  ...options });
    }
  }
});
登入後複製

定义了 api 这个代理之后,我们就可以像下面这样调用:

api.get()
// GET /

api.getUsers()
// 获取所有用户
// GET /users

api.getUsers$Books(42)
// 获取 ID 为 42 的用户的所有书籍
// GET /users/42/books

api.getUsers$Books(42, { params: { page: 2 } })
// 获取 ID 为 42 的用户的所有书籍的第二页
// GET /users/42/books?page=2

api.postUsers({ data: { name: '小明' } })
// 创建名字为 小明 的用户
// POST /users Payload { name: '小明' }
登入後複製

以上所有的函数都在你调用的那一瞬间,通过代理人的魔法之手动态生成,供我们随意取用。

简洁、优雅,哇~ 真是太棒啦!

终极魔幻:通读代理人的魔法秘笈

到此,我们仅仅使用 Proxy 改造了对象的属性获取、赋值操作,而对于 Proxy 来说,只是冰山一角。

Proxy 的基本语法如下:

new Proxy(target, handler)
登入後複製

其中 target 是即将被代理的对象(比如:想要出门找小红玩耍的 me),handler 就是代理的魔法之手,用来拦截、改造 target 的行为。

对于 handler 对象,我们刚才仅仅用到了 getset 函数,而实际上一共有 13 种可代理的操作:

  • handler.getPrototypeOf()

    在读取代理对象的原型时触发该操作,比如在执行 Object.getPrototypeOf(proxy) 时。

  • handler.setPrototypeOf()

    在设置代理对象的原型时触发该操作,比如在执行 Object.setPrototypeOf(proxy, null) 时。

  • handler.isExtensible()

    在判斷一個代理物件是否為可擴展時觸發該操作,例如在執行 Object.isExtensible(proxy) 時。

  • handler.preventExtensions()

    在讓一個代理物件不可擴充時觸發該操作,例如執行 Object.preventExtensions(proxy) 時。

  • handler.getOwnPropertyDescriptor()

    在取得代理物件某個屬性的屬性描述時觸發該動作,例如在執行Object.getOwnPropertyDescriptor(proxy, "foo" ) 時。

  • handler.defineProperty()

    在定義代理物件某個屬性時的屬性描述時觸發該操作,例如在執行Object.defineProperty(proxy, "foo ", {}) 時。

  • handler.has()

    在判斷代理物件是否擁有某個屬性時觸發該操作,例如執行 "foo" in proxy 時。

  • handler.get()

    在讀取代理物件的某個屬性時觸發該操作,例如執行 proxy.foo 時。

  • handler.set()

    在給代理物件的某個屬性賦值時觸發該操作,例如在執行 proxy.foo = 1 時。

  • handler.deleteProperty()

    在刪除代理物件的某個屬性時觸發該操作,例如在執行 delete proxy.foo 時。

  • handler.ownKeys()

    在取得代理物件的所有屬性鍵時觸發該動作,例如執行 Object.getOwnPropertyNames(proxy) 時。

  • handler.apply()

    在呼叫一個目標物件為函數的代理物件時觸發該操作,例如在執行 proxy() 時。

  • handler.construct()

    在給一個目標物件為建構函式的代理物件建構實例時觸發該操作,例如在執行new proxy() 時。

對於以上 13 種可代理的操作,也需要讀者自行研究並實踐方可踏上終極魔幻之旅。

以上是JavaScript代理是什麼? javascript代理的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
集邦諮詢:英偉達 Blackwell 平台產品帶動台積電今年 CoWoS 產能提升 150% 集邦諮詢:英偉達 Blackwell 平台產品帶動台積電今年 CoWoS 產能提升 150% Apr 17, 2024 pm 08:00 PM

本站4月17日消息,集邦諮詢(TrendForce)近日發布報告,認為英偉達Blackwell新平台產品需求看漲,預估帶動台積電2024年CoWoS封裝總產能提升逾150%。英偉達Blackwell新平台產品包含B系列的GPU,以及整合英偉達自家GraceArmCPU的GB200加速卡等。集邦諮詢確認為供應鏈目前非常看好GB200,預估2025年出貨量預計超過百萬片,在英偉達高階GPU中的佔比達到40-50%。在英偉達計畫下半年交付GB200以及B100等產品,但上游晶圓封裝方面須進一步採用更複

PHP與Vue:完美搭檔的前端開發利器 PHP與Vue:完美搭檔的前端開發利器 Mar 16, 2024 pm 12:09 PM

PHP與Vue:完美搭檔的前端開發利器在當今網路快速發展的時代,前端開發變得愈發重要。隨著使用者對網站和應用的體驗要求越來越高,前端開發人員需要使用更有效率和靈活的工具來創建響應式和互動式的介面。 PHP和Vue.js作為前端開發領域的兩個重要技術,搭配起來可以稱得上是完美的利器。本文將探討PHP和Vue的結合,以及詳細的程式碼範例,幫助讀者更好地理解和應用這兩

Oracle API使用指南:探索資料介面技術 Oracle API使用指南:探索資料介面技術 Mar 07, 2024 am 11:12 AM

Oracle是一家全球知名的資料庫管理系統供應商,其API(ApplicationProgrammingInterface,應用程式介面)是一種強大的工具,可協助開發人員輕鬆地與Oracle資料庫互動和整合。在本文中,我們將深入探討OracleAPI的使用指南,向讀者展示如何在開發過程中利用資料介面技術,同時提供具體的程式碼範例。 1.Oracle

Oracle API整合策略解析:實現系統間無縫通信 Oracle API整合策略解析:實現系統間無縫通信 Mar 07, 2024 pm 10:09 PM

OracleAPI整合策略解析:實現系統間無縫通信,需要具體程式碼範例在當今數位化時代,企業內部系統之間需要相互通信和資料共享,而OracleAPI就是幫助實現系統間無縫通信的重要工具之一。本文將從OracleAPI的基本概念和原則入手,探討API整合的策略,最終給出具體的程式碼範例幫助讀者更好地理解和應用OracleAPI。一、OracleAPI基本

如何處理Laravel API報錯問題 如何處理Laravel API報錯問題 Mar 06, 2024 pm 05:18 PM

標題:如何處理LaravelAPI報錯問題,需要具體程式碼範例在進行Laravel開發時,常會遇到API報錯的情況。這些報錯可​​能來自於程式碼邏輯錯誤、資料庫查詢問題或是外部API請求失敗等多種原因。如何處理這些報錯是一個關鍵的問題,本文將透過具體的程式碼範例來示範如何有效處理LaravelAPI報錯問題。 1.錯誤處理在Laravel

Go語言前端技術探秘:前端開發新視野 Go語言前端技術探秘:前端開發新視野 Mar 28, 2024 pm 01:06 PM

Go語言作為一種快速、高效的程式語言,在後端開發領域廣受歡迎。然而,很少有人將Go語言與前端開發聯繫起來。事實上,使用Go語言進行前端開發不僅可以提高效率,還能為開發者帶來全新的視野。本文將探討使用Go語言進行前端開發的可能性,並提供具體的程式碼範例,幫助讀者更了解這一領域。在傳統的前端開發中,通常會使用JavaScript、HTML和CSS來建立使用者介面

AMD 'Strix Halo” FP11 封裝尺寸曝光:和英特爾 LGA1700 相當,比 Phoenix 大 60% AMD 'Strix Halo” FP11 封裝尺寸曝光:和英特爾 LGA1700 相當,比 Phoenix 大 60% Jul 18, 2024 am 02:04 AM

本站7月9日訊息,AMDZen5架構「Strix」系列處理器會有兩種封裝方案,其中較小的StrixPoint將採用FP8封裝,而StrixHalo將會採用FP11封裝。圖源:videocardz訊息源@Olrak29_最新曝料稱StrixHalo的FP11封裝尺寸為37.5mm*45mm(1687平方毫米),和英特爾AlderLake、RaptorLakeCPU的LGA-1700封裝尺寸相同。 AMD最新的PhoenixAPU採用FP8封裝方案,尺寸為25*40mm,這意味著StrixHalo的F

C++ 函式如何透過封裝程式碼來提高 GUI 開發的效率? C++ 函式如何透過封裝程式碼來提高 GUI 開發的效率? Apr 25, 2024 pm 12:27 PM

透過封裝程式碼,C++函數可以提高GUI開發效率:程式碼封裝:函數將程式碼分組到獨立單元,使程式碼易於理解和維護。可重複使用性:函數可建立通用功能供應用程式中重複使用,減少重複編寫和錯誤。簡潔程式碼:封裝程式碼讓主邏輯簡潔,方便閱讀和除錯。

See all articles