ES6 代理和反射
簡介
-
proxy
proxy
可以攔截目標(target)上的非內建的物件進行操作,使用trap
攔截這些操作,trap
是響應特定操作的方法。 -
reflection
reflection
是通過Reflect
物件表示,他提供了一些方法集,為代理proxy
提供預設行為。
下面是一些proxy trap
和Reflect
方法,每個proxy trap
都有提供對應的Reflect
方法,他們接收相同的引數。
Proxy Trap | Overrides the Behavior Of | Default Behavior |
---|---|---|
get | Reading a property value | Reflect.get() |
set | Writing to a property | Reflect.set() |
has | The in operator | Reflect.has() |
deleteProperty | The delete operator | Reflect.deleteProperty() |
getPrototypeOf | Object.getPrototypeOf() | Reflect.getPrototypeOf() |
setPrototypeOf | Object.setPrototypeOf() | Reflect.setPrototypeOf() |
isExtensible | Object.isExtensible() | Reflect.isExtensible() |
preventExtensions | Object.preventExtensions() | Reflect.preventExtensions() |
getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor() | Reflect.getOwnPropertyDescriptor() |
defineProperty | Object.defineProperty() | Reflect.defineProperty |
ownKeys | Object.keys, Object.getOwnPropertyNames(), Object.getOwnPropertySymbols() | Reflect.ownKeys() |
apply | Calling a function | Reflect.apply() |
construct | Calling a function with new | Reflect.construct() |
這裡的每個trap
都會覆蓋物件的內建行為,便於攔截和修改物件。如果你真的需要內建行為,可以使用相對應的Reflect
方法。
開始的時候,
ES6
的規範有個enumerate trap
,用於改變for..in
和Object.keys
的列舉屬性,但是在實行的時候發現有些困難,於是在ES7
中移除了。所以這裡不討論他。
建立一個簡單的代理
當你使用Proxy
的建構函式去建立代理的時候,他接受兩個引數,一個是目標物件(target),另外一個是處理物件(handler)。這個handler
定義了一個或者多個trap
去處理代理,如果沒有定義trap
,那麼就會使用預設的行為。
let target = {};
let proxy = new Proxy(target, {});
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
console.log(target.name); // "proxy"
target.name = "target";
console.log(proxy.name); // "target"
console.log(target.name); // "target"
從上面這個例子可以發現,不管是proxy
或者是target
的屬性更改,都會影響到另外一個。其實這就是這兩個的關係: **proxy
本身不儲存這個屬性,他只是把操作轉發到target
。**上面的這個例子似乎沒啥意思,並沒有體現出核心trap
的價值所在。
使用set trap
驗證屬性
set trap
是在設定屬性值時觸發。
set trap
接收這幾個引數:
trapTarget
- 接收的屬性的物件,就是代理的目標。key
- 要寫入的屬性的key
(string || symbol
)value
- 寫入屬性的值receiver
- 操作的物件,通常是代理
Reflect.set
是set trap
相對應的方法。如果屬性被設定,那麼trap
應該返回true
,如果沒有被設定,那就返回false
。Reflect.set()
會根據操作是否成功返回正確的值。
要驗證一個屬性的值,那就需要使用set
trap來檢查這個值,看下面程式碼:
let target = {
name: "target"
};
let proxy = new Proxy(target, {
set(trapTarget, key, value, receiver) {
console.log(`trapTarget is ${trapTarget}, key is ${key}, value is ${value}, receiver is ${receiver}`)
// 忽視存在的屬性,以免產生影響
if (!trapTarget.hasOwnProperty(key)) {
if (isNaN(value)) {
throw new TypeError("Property must be a number.");
}
}
// 新增到屬性
return Reflect.set(trapTarget, key, value, receiver);
}
});
// 新增一個新的屬性
proxy.count = 1;
console.log(proxy.count); // 1
console.log(target.count); // 1
// 賦值給存在target上的屬性
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
console.log(target.name); // "proxy"
// 新的屬性值不是數字會丟擲異常
proxy.anotherName = "proxy";
可以發現,每次設定屬性值的時候都會進行攔截判斷,所以,相對的,你在獲取的時候,可以使用get
進行攔截判斷。
使用get trap
驗證
js
一個有趣又令人困惑的地方就是獲取一個不存在的屬性的時候,不會丟擲異常,只會返回一個undefined
。不像其他的大多數語言,都會丟擲一個錯誤,可能你寫了大量的程式碼,你可能會意識到這是一個嚴重的問題,比如拼寫錯誤的這些問題,代理可以為你處理這些。
**get
是在讀取物件屬性的時候用到的trap
。**他接收三個引數:
trapTarget
- 從哪個物件讀取的屬性,就是target.key
- 讀取的key
receiver
- 操作的物件,通常是代理(proxy)
可以發現這個和上面的set
差不多,就是少了一個設定的value
引數。相對的,Reflect.get
方法接受與get trap
相同的三個引數,並返回屬性的預設值。
var proxy = new Proxy({}, {
get(trapTarget, key, receiver) {
if (!(key in receiver)) {
throw new TypeError("Property " + key + " doesn't exist.");
}
return Reflect.get(trapTarget, key, receiver);
}
});
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
// 不存在這個屬性,丟擲錯誤
console.log(proxy.age); // throws error
不知道你有沒有發現,我們在這裡使用receiver
代替trapTarget
配合in
一起使用,我們將在下面介紹。
使用has trap
隱藏屬性的存在
in
這個操作想來大家比較熟悉的,是確定屬性是否存在物件及原型鏈上。
var target = {
value: 42;
}
console.log("value" in target); // true
console.log("toString" in target); // true
代理允許你使用has
這個trap
去返回不同的值。
這個has trap
是在使用in
操作時觸發。has trap
接收兩個引數:
trapTarget
key
Reflect.has
方法接受這些相同的引數並返回in
運算子的預設響應。使用has trap
和Reflect.has
可以改變某些屬性的in
行為,同時又回退到其他屬性的預設行為。例如你只想隱藏value
屬性:
var target = {
name: "target",
value: 42
};
var proxy = new Proxy(target, {
has(trapTarget, key) {
if (key === "value") {
return false;
} else {
return Reflect.has(trapTarget, key);
}
}
});
console.log("value" in proxy); // false
console.log("name" in proxy); // true
console.log("toString" in proxy); // true
可以發現上例直接判斷,如果不是value key
,就使用Reflect
去返回其預設行為。
使用deleteProperty trap
對刪除進行操作
通過屬性描述那部分我們知道,delete
是通過configurable
來控制的,非嚴格模式下刪除會返回false
,嚴格模式下會報錯。但是我們可以使用代理deleteProperty trap
去操作他這個行為。
下面我們再來看看deleteProperty
這個trap
。他也是接受兩個引數:
trapTarget
key
Reflect.deleteProperty
方法提供了deleteProperty trap
相對的行為去實現。所以我們可以使用這兩個去改變delete
的預設行為。
let target = {
name: "target",
value: 42
};
let proxy = new Proxy(target, {
deleteProperty(trapTarget, key) {
if (key === "value") {
return false;
} else {
return Reflect.deleteProperty(trapTarget, key);
}
}
});
// Attempt to delete proxy.value
console.log("value" in proxy); // true
let result1 = delete proxy.value;
console.log(result1); // false
console.log("value" in proxy); // true
// Attempt to delete proxy.name
console.log("name" in proxy); // true
let result2 = delete proxy.name;
console.log(result2); // true
console.log("name" in proxy); // false
這樣可以攔截操作,好奇的你可能會想去操作nonconfigurable
的時候,也可以刪除,你可以嘗試一下。這個方法在受保護的屬性被刪除的時候,非嚴格模式下會拋錯。
原型的代理trap
在這個章節裡介紹了setPrototypeOf
和getPrototypeOf
。代理也為這兩種情況添加了相應的trap
。針對這兩個代理的trap
,都有不同的引數:
- setPrototypeOf
trapTarget
proto
這個用作原型的物件
他和Reflect.setPrototypeOf
接收的引數相同,去做相對應的操作。另一方面,getPrototypeOf
只接收一個引數trapTarget
,相應的也存在Reflect.getPrototypeOf
方法.
原型代理是如何工作的
他們有一些限制。首先,getPrototypeOf
只可以返回物件或者null
,返回其他的,在執行的時候會報錯。同樣的,setPrototypeOf trap
如果失敗,必須返回false
,並且Object.setPrototypeOf
會拋錯, 如果返回其他的值,那就是認為操作成功。
下面來看一個例子:
var target = {};
var proxy = new Proxy(target, {
getPrototypeOf(trapTarget) {
return null;
},
setPrototypeOf(trapTarget, proto) {
return false;
}
});
var targetProto = Object.getPrototypeOf(target);
var proxyProto = Object.getPrototypeOf(proxy);
console.log(targetProto === Object.prototype); // true
console.log(proxyProto === Object.prototype); // false
console.log(proxyProto); // null
// succeeds
Object.setPrototypeOf(target, {});
// throws error
Object.setPrototypeOf(proxy, {});
從上面可以發現,對於proxy
進行了攔截,以至於原型不同。然後對proxy
進行setPrototypeOf
會丟擲異常,就是上面提到的,setPrototypeOf
返回false
,那麼Object.setPrototypeOf
會丟擲錯誤。
當然,如果你想要使用它的預設行為,那就需要使用Reflect
物件的方法來操作。
為什麼會有兩套方法
讓人感到困惑的是, setPrototypeOf trap
和getPrototypeOf trap
看起來和Object.getPrototypeOf() or Object.setPrototypeOf()
看起來類似,為什麼還要這兩套方法。其實他們看起來是類似,但是還有很大的差異:
首先,Object.getPrototype||Object.setPrototypeOf
在一開始就是為開發人員建立的高級別的操作。然而Reflect.getPrototypeOf || Reflect.setPrototypeOf
是提供了操作以前僅僅用於內部的[[GetPrototypeOf]] || [[SetPrototypeOf]]
的底層屬性。Reflect.getPrototypeOf
方法是內部[[GetPrototypeOf]]
操作的包裝器(帶有一些輸入驗證)。Reflect.setPrototypeOf
方法和[[SetPrototypeOf]]
具有相同的關係。Object
上的相應方法也呼叫[[GetPrototypeOf]]
和[[SetPrototypeOf]]
,但在呼叫之前執行幾個步驟並檢查返回值以確定如何操作。
上面說的比較泛泛,下面來詳細說下:
如果Reflect.getPrototypeOf
方法的引數不是物件或者null
,則丟擲錯誤;而Object.getPrototypeOf
在執行操作之前首先將值強制轉換為物件。
var result1 = Object.getPrototypeOf(1);
console.log(result1 === Number.prototype); // true
// throws an error
Reflect.getPrototypeOf(1);
很明顯,Object
上的可以工作,他把數字1
轉換成了物件,Reflect
上的不會進行轉換,所以丟擲異常。
setPrototypeOf
也有一些不同,Reflect.setPrototypeOf
會返回一個布林來確定是否成功,false
就是失敗。然而Object.setPrototypeOf
如果失敗,會丟擲錯誤。
物件 Extensibility trap
ECMAScript 5
通過Object.preventExtensions
和Object.isExtensible
方法添加了物件可擴充套件性的操作,因此ES6
在此基礎上對這兩個方法添加了代理。並且這兩個代理方法都只接收一個引數trapTarget
.isExtensible trap
必須返回布林值來確定是否是可擴充套件的,preventExtensions trap
返回布林值確定是否成功。
Reflect
物件裡的這兩個方法都會返回布林值,所以這兩個是可以作為相對應的方法去使用實現預設行為。
兩個簡單的例子
var target = {};
var proxy = new Proxy(target, {
isExtensible(trapTarget) {
return Reflect.isExtensible(trapTarget);
},
preventExtensions(trapTarget) {
return Reflect.preventExtensions(trapTarget);
}
});
console.log(Object.isExtensible(target)); // true
console.log(Object.isExtensible(proxy)); // true
Object.preventExtensions(proxy);
console.log(Object.isExtensible(target)); // false
console.log(Object.isExtensible(proxy)); // false
這個例子就是使用代理攔截並返回他的預設行為,等於預設的情況。所以經過Object
屬性操作之後,就是返回預設的行為。
如果我們不想他拓展,我們可以這樣去處理:
var target = {};
var proxy = new Proxy(target, {
isExtensible(trapTarget) {
return Reflect.isExtensible(trapTarget);
},
preventExtensions(trapTarget) {
return false
}
});
console.log(Object.isExtensible(target)); // true
console.log(Object.isExtensible(proxy)); // true
Object.preventExtensions(proxy);
console.log(Object.isExtensible(target)); // true
console.log(Object.isExtensible(proxy)); // true
這裡他不會成功,因為返回了false
,沒有使用對應的Reflect
去做相對的預設行為處理,所以操作不會轉發到操作的目標。
Duplicate Extensibility Methods
如果傳遞物件值作為引數,方法Object.isExtensible
和Reflect.isExtensible
類似。如果不是物件作為引數傳遞,Object.isExtensible
始終返回false
,而Reflect.isExtensible
則丟擲錯誤。
let result1 = Object.isExtensible(2);
console.log(result1); // false
// throws error, Reflect.isExtensible called on non-object
let result2 = Reflect.isExtensible(2);
這個限制類似於Object.getPrototypeOf
和Reflect.getPrototypeOf
方法之間的差異,因為具有較低級別功能的方法具有比其更高級別對應方更嚴格的錯誤檢查。
Object.preventExtensions
和Reflect.preventExtensions
方法也非常相似。 Object.preventExtensions
方法始終返回作為引數傳遞給它的值,即使該值不是物件也是如此。然而另一方面,如果引數不是物件,那麼Reflect.preventExtensions
方法會丟擲錯誤;如果引數是一個物件,那麼Reflect.preventExtensions
在操作成功時返回true
,否則返回false
。
var result1 = Object.preventExtensions(2);
console.log(result1); // 2
var target = {};
var result2 = Reflect.preventExtensions(target);
console.log(result2); // true
// throws error
var result3 = Reflect.preventExtensions(2);
這個例子就是對上面的總結。
Property Descriptor Traps
ECMAScript 5
最重要的功能之一是使用Object.defineProperty
方法定義屬性具體屬性的能力。在以前的JavaScript版本中,無法定義訪問者屬性,使屬性成為只讀,或使屬性不可數。具體參考這裡
代理允許分別使用defineProperty trap
和getOwnPropertyDescriptor trap
攔截對Object.defineProperty
和Object.getOwnPropertyDescriptor
的呼叫。 defineProperty trap
接收以下引數:
trapTarget
- 被定義屬性的物件(代理的目標)key
descriptor
defineProperty trap
返回布林值。getOwnPropertyDescriptor trap
只接收trapTarget
和key
,並且返回描述資訊。相應的Reflect.defineProperty
和Reflect.getOwnPropertyDescriptor
方法接受與其代理trap
對應方相同的引數。
例如:
var proxy = new Proxy({}, {
defineProperty(trapTarget, key, descriptor) {
return Reflect.defineProperty(trapTarget, key, descriptor);
},
getOwnPropertyDescriptor(trapTarget, key) {
return Reflect.getOwnPropertyDescriptor(trapTarget, key);
}
});
Object.defineProperty(proxy, "name", {
value: "proxy"
});
console.log(proxy.name); // "proxy"
var descriptor = Object.getOwnPropertyDescriptor(proxy, "name");
console.log(descriptor.value); // "proxy"
很簡單的一個例子,基本沒有在攔截上做任何操作,只是返回他的預設行為。
Blocking Object.defineProperty()
trap
返回true
時,Object.defineProperty
表示成功;
trap
返回false
時,Object.defineProperty
會丟擲錯誤。
可以使用這個功能來限制Object.defineProperty
方法可以定義的屬性型別.如下:
var proxy = new Proxy({}, {
defineProperty(trapTarget, key, descriptor) {
if (typeof key === "symbol") {
return false;
}
return Reflect.defineProperty(trapTarget, key, descriptor);
}
});
Object.defineProperty(proxy, "name", {
value: "proxy"
});
console.log(proxy.name); // "proxy"
var nameSymbol = Symbol("name");
// throws error
Object.defineProperty(proxy, nameSymbol, {
value: "proxy"
});
這裡我們檢測key
的型別,如果是symbol
就返回false
.對於Object.defineProperty
,返回false
會丟擲異常。
當然可以通過返回
true
而不呼叫Reflect.defineProperty
方法使Object.defineProperty
預設是失敗的,這就避免錯誤的丟擲。
Descriptor Object Restrictions
為了確保在使用Object.defineProperty
和Object.getOwnPropertyDescriptor
方法時的一致行為,傳遞給defineProperty trap
的描述符物件被規範化。從getOwnPropertyDescriptor trap
返回的物件總是出於同樣的原因進行驗證。
不管哪個引數作為第三個引數傳遞給Object.defineProperty
方法,都只能是下面這幾種:enumerable
, configurable
, value
, writable
, get
, set
這些將被作為descriptor
傳遞。例如:
var proxy = new Proxy({}, {
defineProperty(trapTarget, key, descriptor) {
console.log(descriptor.value); // "proxy"
console.log(descriptor.name); // undefined
console.log(descriptor.writable) // undefined
return Reflect.defineProperty(trapTarget, key, descriptor);
}
});
Object.defineProperty(proxy, "name", {
value: "proxy",
name: "custom"
});
可以發現,name
不存在那幾個descriptor
裡,所以傳遞不進去,不接收。並且這個和Object.defineProperty
不同,沒有進行一些包裝,不存在預設的writable
, configurable
這些…。但是按理來說,你傳遞一個物件進行,他就應該接收啊,為啥這裡會是undefined
呢?這是因為**descriptor
實際上不是對傳遞給Object.defineProperty
方法的第三個引數的引用,而是一個僅包含允許屬性的新物件。Reflect.defineProperty
方法還會忽略描述符上的任何非標準屬性**
getOwnPropertyDescriptor
稍微有些不同,他會返回null
, undefined
,object
.如果返回的是物件,那麼物件只會包含上面可能出現的descriptor
的這幾種情況。
如果返回具有不允許的屬性的物件,會導致錯誤,如下程式碼:
var proxy = new Proxy({}, {
getOwnPropertyDescriptor(trapTarget, key) {
return {
name: "proxy"
};
}
});
// throws error
var descriptor = Object.getOwnPropertyDescriptor(proxy, "name");
因為name
不屬於descriptor
接受的範圍,所以引發了錯誤。這個限制可確保Object.getOwnPropertyDescriptor
返回的值始終具有可靠的結構,無論代理使用什麼。
Duplicate Descriptor Methods
和上面的一些trap
類似,這個也有一些讓人為之困惑的類似的方法。這裡的是Object.defineProperty&Object. getOwnPropertyDescriptor
和Reflect. defineProperty&Reflect.getOwnPropertyDescriptor
.
defineProperty() Methods
看看這個方法的異同.
Object.defineProperty
和Reflect.defineProperty
方法完全相同,只是它們的返回值有所不同。
相關推薦
ES6 代理和反射
此文出處 簡介 proxy proxy可以攔截目標(target)上的非內建的物件進行操作,使用trap攔截這些操作,trap是響應特定操作的方法。 reflection reflection是通過Reflect物件表示,他提供了一些方法集,為代理proxy提
ES6躬行記(24)——代理和反射
代理和反射是ES6新增的兩個特性,兩者之間是協調合作的關係,它們的具體功能將在接下來的章節中分別講解。 一、代理 ES6引入代理(Proxy)地目的是攔截物件的內建操作,注入自定義的邏輯,改變物件的預設行為。也就是說,將某些JavaScript內部的操作暴露了出來,給予開發人員更多的許可權。這其實
深入理解ES6之——代理和反射(proxy)
通過呼叫new proxy()你可以建立一個代理來替代另一個物件(被稱為目標),這個代理對目標物件進行了虛擬,因此該代理與該目標物件表面上可以被當做同一個物件來對待。 建立一個簡單的代理 當你使用Proxy構造器來建立一個代理時,需要傳遞兩個引數:目標物件以及一個處理器,後者是定義了一個或多個陷阱函式的物件。
java中的動態代理和反射
java的動態代理是用反射實現的。 什麼是反射? java的反射機制,是說在執行時刻,對於任何一個類,都能夠知道它的所有屬性和方法;對任意一個物件,都能夠呼叫它的任意方法和屬性;這種動態獲取資訊以及動態呼叫方法的功能稱為java的反射機制。 java通過j
Java高階特性(動態代理和反射)
目錄第4天 java高階特性增強今天內容安排:1、掌握多執行緒2、掌握併發包下的佇列3、瞭解JMS4、掌握JVM技術5、掌握反射和動態代理Øjava多執行緒增強通俗來講:應用程式就是一個程序。不管是我們開發的應用程式,還是我們執行的其他的應用程式,都需要先把程式安裝在本地的硬
類載入器(Mapper動態代理)和反射
類的載入: 當程式要使用某個類時,如果該類還未被載入到記憶體中,則系統會通過載入,連線,初始化三步來實現對這個類進行初始化。 一:載入 就是指將class檔案讀入記憶體,併為之建立一個Class物件。 任何類被
ES6的代理Proxy和反射Reflect
一、Proxy Proxy(代理)是 ES6 中新增的一個特性。Proxy 讓我們能夠以簡潔易懂的方式控制外部對物件的訪問。其功能非常類似於設計模式中的代理模式。 使用 Proxy 的好處是:物件只需關注於核心邏輯,一些非核心的邏輯(如:讀取或設定物件的某些屬性前記錄日誌;設定物件的
類的加載機制和反射——五、使用反射生成JDK動態代理
復用 他也 new mil ont throwable logs object load 使用反射生成JDK動態代理 1.使用Proxy和InvocationHandler創建動態代理 (1)Proxy提供了用於創建動態代理類和動態代理對象的靜態方法,他也是所有動態代理類的
ES6語法和知識點:代理proxy
Proxy 可以理解成,在目標物件之前架設一層“攔截”,外界對該物件的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。 var obj = new Proxy({}, { get: function (target, key, recei
nginx+tomcat實現反射代理和域名繫結專案
Nginx反向代理設定如下: upstream admin { server 127.0.0.1:8080;(將請求轉發到的實際容器tomcat埠) } server { listen 80; server_name _;(這個地方設定需要反向代理的域名,如www.
深入理解ES6--迭代器、生成器、代理、反射、Promise
迭代器(Iterator)和生成器(Generator) for-of迴圈及展開運算子…都是針對迭代器的!!! 不能使用箭頭函式來建立生成器;ES6函式的簡寫方式可以(只需在函式名前加星號) 可迭代物件具有Symbol.iterator屬性,ES6
深入理解ES6--12.代理與反射介面
主要知識點:代理和反射的定義、常用的陷阱函式、可被撤銷的代理、將代理物件作為原型使用、將代理作為類的原型 1. 代理和反射 代理是什麼? 通過呼叫 new Proxy() ,你可以建立一個代理用來替代另一個物件(被稱之為目目標物件)
【ES6】改變 JS 內置行為的代理與反射
instance 什麽 del handle efault list sta clas 接受 代理(Proxy)可以攔截並改變 JS 引擎的底層操作,如數據讀取、屬性定義、函數構造等一系列操作。ES6 通過對這些底層內置對象的代理陷阱和反射函數,讓開發者能進一步接近 JS
JAVA的回撥函式和反射機制(原理不說直接看程式碼),補充動靜態代理
程式碼都是轉載或抄錄這個地址: http://blog.csdn.net/zhandoushi1982/article/details/8567709 http://blog.csdn.net/xiaanming/article/details/8703708/ 反射機制
使用閉包和代理和Segue進行反向傳值
closure create 賦值 返回 protocol alt 類型 del uiview import UIKit class FirstViewController: UIViewController, SecondViewControllerDelegate
侃侃正向代理和反向代理
nginx 是我 應用 技術 關系 str 它的 技術分享 服務器 正向代理 比如你現在缺錢,想找馬雲爸爸去借錢,可想而知人家可能鳥都不鳥你,到最後碰一鼻子灰借不到錢。不過你認識你家隔壁老王,而老王認識馬雲同誌,而且關系還很好。這時候你托老王去找馬雲借錢,當然這事最後成了,
es6--let和const
標簽 cau ria ble ready 復合 iss 模式 ren 參考資料: http://es6.ruanyifeng.com/#docs/let 測試環境(本文的代碼均是在chrome下運行) 在<script>標簽中添加‘use strict
es6 let和const
ons defined ria ole tar iss 聲明 htm love 一、let 1、let塊作用域 if(true){ var a=1; let b=2; } con
Nginx反向代理和負載均衡部署指南
命令 eva http ddr cli 僅支持 新版 ive app nginx不單能夠作為強大的webserver,也能夠作為一個反向代理server,並且nginx還能夠依照調度規則實現動態、靜態頁面的分離。能夠依照輪詢、ip哈希、URL哈希、權重等多種
es6 map()和filter()詳解【轉】
低版本 window get 簡約 push foreach 沒有 數值 length 原文地址:http://www.zhangxinxu.com/wordpress/2013/04/es5%e6%96%b0%e5%a2%9e%e6%95%b0%e7%bb%84%e