iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
佛心分享-IT 人自學之術

Ai大時代透過vibe coding 逆向學習回來系列 第 3

Ai大時代透過vibe coding 逆向學習回來 - Day3 我又忘了 Proxy:跟 AI 重新學一次的過程

  • 分享至 

  • xImage
  •  

我又忘記 js proxy,你可以幫我做一個教學互動的網頁嗎?

這是我丟給 AI 的第一句話。

我想要的不是一篇文字說明,而是可以按、可以看到結果的東西。


先用一句話認識 Proxy

在講過程之前,先說 Proxy 是什麼。

JavaScript 的物件長這樣:

const user = { name: '小明', age: 18 }

平常我們讀取 user.name、修改 user.age = 20,都是直接對物件操作,中間沒有任何人知道。

Proxy(代理)就是在物件前面放一個「守門人」。 之後每次讀取或修改,都要先經過守門人,它可以記錄、檢查,甚至拒絕這次操作。


AI 做出來的互動網頁

AI 做的網頁,最上方就是這個守門人的流程圖:

你的程式  →  Proxy 守門人  →  原本的物件

畫面上有幾個按鈕:

  • 按「讀取 user.name」,箭頭亮起來,守門人記下「有人讀了 name」
  • 按「設定 user.age = -5」,守門人發現年齡不能是負數,直接擋下來

看完這個畫面,我終於抓到重點:Proxy 不是去改物件本身,而是站在物件前面把關。

每一步都先問我問題

網頁下面分成好幾個步驟,每一步都會先出一道思考題,想完再按「看答案」。

第一題是:

每次有人讀取或修改 user 的資料,就要印出一行紀錄。但大家還是照常寫 user.name,不能改成別的寫法。你會怎麼做?

我想了一下,只想到一個比較舊的方法 Object.defineProperty,它可以替物件的「某一個屬性」加上監聽。

展開答案後,AI 剛好從這個方法講起,並指出它的問題:

  • 要一個屬性一個屬性設定name 設定完,age 還要再設定一次
  • 之後新加的屬性聽不到:如果後來寫 user.hobby = '畫畫',完全不會被記錄

然後才帶出 Proxy:守門人管的是整個物件,不管是哪個屬性、什麼時候加的,全部都會經過它。

因為我先自己想過,再看到答案,比直接讀說明更容易記住。


Proxy 最基本的寫法

網頁裡的範例大概是這樣:

const user = { name: '小明', age: 18 }

const p = new Proxy(user, {
  get(target, key) {
    console.log('有人讀取了 ' + key)
    return target[key]
  }
})

p.name // 印出「有人讀取了 name」,並拿到 '小明'

拆開來看:

  • new Proxy(物件, 規則):幫 user 建立一個守門人 p
  • get:「讀取」時要做的事,名字是固定的
  • target:原本的物件,也就是 user
  • key:這次被讀取的屬性名稱,例如 'name'

之後只要透過 p 讀取資料,get 就會先被執行。


挑戰題:按下執行才發現自己沒懂

網頁最後有一道挑戰題:

讓陣列可以用 arr[-1] 拿到最後一個元素。

一般的陣列 ['🍎', '🍌', '🍇']arr[-1] 會拿到 undefined。挑戰是用 Proxy 讓它拿到 '🍇'

網頁給了幾個版本讓我猜哪個是對的,每個都能直接按「執行」。其中一個版本我覺得完全沒問題:

get(target, key) {
  if (key < 0) {
    return target[target.length + key]
  }
  return target[key]
}

想法很直覺:如果 key 是負數,就用「陣列長度 + key」算出位置。長度是 3,3 + (-1) = 2,剛好是最後一個。

結果按下執行,拿到的還是 undefined

為什麼?

關鍵在於:守門人收到的 key 永遠是字串,不是數字。

我們寫 arr[-1],守門人收到的其實是 '-1'(有引號的字串)。

所以這行:

target.length + key

實際上是:

3 + '-1'

在 JavaScript 裡,數字加上字串會變成「把字串接起來」,就像 1 + '1' 會得到 '11'。所以結果是 '3-1',陣列裡當然沒有叫 '3-1' 的位置。

正確的做法是先把 key 轉成數字,再來計算。

如果只是用讀的,我很可能看不出這個錯誤。親手按下執行、看到結果跟預期不一樣,才真的記住「key 是字串」。


把自己的疑問丟回去問

看完網頁,我還有一個疑問:

為什麼我看到其他教學,get 和 set 裡面的參數寫法都不太一樣?

我看過有人寫 get(target, key),有人寫 get(target, prop),還有人寫 set(value) 只有一個參數,一直搞不清楚哪個才對。

AI 一樣先丟問題給我:

set(a, b, c) {
  a[b] = c
  return true
}

參數改成 a、b、c,還能正常運作嗎?

答案是可以

參數的名字是我們自己取的,JavaScript 只看順序

第 1 個參數 第 2 個參數 第 3 個參數
get 原本的物件 屬性名稱
set 原本的物件 屬性名稱 要存進去的值

大家常寫 keyvalue,只是因為物件本來就是「key: value」的結構,讀起來比較好懂。

set(value) 只有一個參數又是怎麼回事?AI 告訴我,那是另一種寫法,不是 Proxy:

const user = {
  _name: '小明',
  get name() { return this._name },
  set name(value) { this._name = value }
}

這種寫法是直接寫在物件裡,而且只管 name 這一個屬性。它已經知道自己負責的是 name,所以不需要再傳屬性名稱進來。

Proxy 就不一樣了,它管的是整個物件,任何屬性被讀取都會進到同一個 get,所以一定要告訴它「這次是哪個屬性」。

原來我一直把這兩種寫法混在一起看。


要小心的地方

看懂不等於學會。 AI 的解說很流暢,每一句都讀得懂,很容易以為自己學會了。思考題和挑戰題一定要先自己想,不要直接看答案。

細節要回去看官方文件。 AI 的解說適合用來入門,參數順序這些細節,我還是會再對照 MDN 確認。


結語

真正讓我記住 Proxy 的,是按下執行卻拿到 undefined 的那一刻,還有把疑問問出口的那一次。AI 做的事,是讓這些時刻更容易發生。

如果你也有學過又忘記的觀念,可以試試看:別問「X 是什麼」,改問「可以幫我做一個互動教學嗎?」



上一篇
Ai大時代透過vibe coding 逆向學習回來 - Day2 小試身手:從一集 Podcast 到一個時程規劃器
下一篇
Ai大時代透過vibe coding 逆向學習回來 - Day4 搞清楚再出發
系列文
Ai大時代透過vibe coding 逆向學習回來5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言