摘要:另一部分就是類型的屬性,也就是返回的屬性。,一開始提案為,其作用就是遞歸的將數(shù)組展平到指定深度,默認(rèn)深度為。目前在使用時(shí),我們唯一的選擇是命令行界面。
TypeScript 3.3 更新梳理
Object.assign vs Object Spread in Node.js
New in Chrome 72
New JavaScript features in ES2019
iOS 12.2 Beta"s 支持 Web Share API
Yarn"s Future - v2 and beyond
TypeScript 3.3 更新梳理首先需要聲明的是,TypeScript 3.3 是個(gè)小版本 release,不包含 breaking changes,so 升級(jí)的話應(yīng)該比較輕松。那么 3.3 中有什么新東西呢?我們一起來探索一下。
聯(lián)合類型(union types)的優(yōu)化 先梳理一下我們先梳理下之前聯(lián)合類型是怎樣的。假設(shè)我們有聯(lián)合類型 A | B,則可以訪問 A 或 B 共有的屬性或方法(也就是 A 或 B 的交集)。
interface A { aProp: string; commonProp: string; } interface B { bProp: number; commonProp: number } type Union = A | B; declare let x: Union; x.aProp; // error - "B" doesn"t have the property "aProp" x.bProp; // error - "A" doesn"t have the property "bProp" x.commonProp; // okay! Both "A" and "B" have a property named `commonProp`.
這一點(diǎn)還是符合直覺的,我們只能訪問聯(lián)合類型的公共部分,這一點(diǎn)頗有些像多態(tài)性。
而當(dāng)我們不是想訪問屬性,而是想處理調(diào)用方法的返回類型時(shí),當(dāng)然,不論是什么類型,我們的標(biāo)識(shí)符參數(shù)都是一樣的,那么也一樣 work:
type CallableA = (x: boolean) => string; type CallableB = (x: boolean) => number; type CallableUnion = CallableA | CallableB; declare let f: CallableUnion; let x = f(true); // Okay! Returns a "string | number".更新點(diǎn)
但是問題來了,有時(shí)候這些約束還是會(huì)有些嚴(yán)格了,我們來看下面的例子:
type Fruit = "apple" | "orange"; type Color = "red" | "orange"; type FruitEater = (fruit: Fruit) => number; // eats and ranks the fruit type ColorConsumer = (color: Color) => string; // consumes and describes the colors declare let f: FruitEater | ColorConsumer; // Cannot invoke an expression whose type lacks a call signature. // Type "FruitEater | ColorConsumer" has no compatible call signatures.ts(2349) f("orange");
上面的例子就相對復(fù)雜了些,除了聯(lián)合類型還用到了 declare 聲明關(guān)鍵字和 type 別名關(guān)鍵字。我們調(diào)用了函數(shù) f,而函數(shù) f 的聲明表示,它是 FruitEater 和 ColorConsumer 的聯(lián)合類型,其中,F(xiàn)ruitEater 和 ColorConsumer 分別是兩種自定義的函數(shù)類型的別名,而它們的函數(shù)參數(shù)也都是聯(lián)合類型。
這個(gè)代碼很傻瓜但卻報(bào)了錯(cuò),F(xiàn)ruitEater 和 ColorConsumer 都應(yīng)該能夠接收 "orange" 參數(shù),它既可以返回一個(gè)數(shù)字,也可以返回一個(gè)字符串。
上述的問題在 TypeScript 3.3 中被干掉了:
type Fruit = "apple" | "orange"; type Color = "red" | "orange"; type FruitEater = (fruit: Fruit) => number; // eats and ranks the fruit type ColorConsumer = (color: Color) => string; // consumes and describes the colors declare let f: FruitEater | ColorConsumer; f("orange"); // It works! Returns a "number | string". f("apple"); // error - Argument of type ""apple"" is not assignable to parameter of type ""orange"". f("red"); // error - Argument of type ""red"" is not assignable to parameter of type ""orange"".
上面就很清晰了,"orange" 符合聯(lián)合類型的要求,所以 f 應(yīng)該可以接收并正確返回,我們只需要保證返回的值是數(shù)字或者字符串就夠了。
在 TypeScript 3.3 中,這些交叉的類型會(huì)創(chuàng)建新的簽名。舉個(gè)例子,F(xiàn)ruitEater 和 ColorConsumer 的參數(shù) fruit 和 color 被交叉成了一個(gè)新的參數(shù)類型:Fruit & Color,如替換掉別名,F(xiàn)ruit & Color 實(shí)際上就是 ("apple" | "orange") & ("red" | "orange"),我們繼續(xù)演進(jìn),其實(shí)就是 ("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange")。而我們?nèi)〗患\(yùn)算后,最后得到的結(jié)果就是 "orange" & "orange",也就是 "orange"。
我們整理一下,用數(shù)學(xué)中集合那一塊的運(yùn)算重新演算一遍:
Fruit & Color = ("apple" | "orange") & ("red" | "orange") = ("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange") = "orange" & "orange" = "orange"
日了狗了,我不就寫寫 JS 嗎,怎么算起了數(shù)學(xué)呢?萬惡的 MS...
復(fù)合項(xiàng)目的增量 watchTypeScript 3.0 引入了一個(gè)用于構(gòu)建過程的被稱為「復(fù)合項(xiàng)目」的新功能。 其目的有二:
確保用戶可以將大型項(xiàng)目拆分為更小的部分,從而快速構(gòu)建
保留項(xiàng)目結(jié)構(gòu),不影響現(xiàn)有的 TypeScript 體驗(yàn)
在3.3版本之前,在使用 --build、--watch 構(gòu)建復(fù)合項(xiàng)目時(shí),實(shí)際上并沒有使用 watch 增量文件的基礎(chǔ)結(jié)構(gòu)。 如果一個(gè)項(xiàng)目中有了更新,將會(huì)強(qiáng)制完全重新構(gòu)建該項(xiàng)目,而不是檢查項(xiàng)目中有哪些文件受到影響。
在TypeScript 3.3中, --build 模式的 --watch 標(biāo)志也可以利用增量文件機(jī)制進(jìn)行監(jiān)視了。這意味著在 --build --watch 模式下構(gòu)建速度能將更快。測試下來的構(gòu)建時(shí)間比原來縮短了 50% 到 75%。
接下來的發(fā)展我們可以在 roadmap 里看到接下來的發(fā)展路線。TypeScript 3.4 中我們就可以用上「只讀 數(shù)組和元組」和 const 上下文了,后續(xù)我們再看吧。
源地址:https://blogs.msdn.microsoft....
Object.assign vs Object Spread in Node.js今天來比較下 Object.assign 和 Object Spread 的差異。
因?yàn)槲覀冊陧?xiàng)目中配了 Babel,所以這兩個(gè)也是常用的。其中,2018 年的時(shí)候,[Ojbect Rest/Spread Proposal] 提案就已經(jīng)到了 stage 4,也就是說不久就會(huì)進(jìn)入 ECMAScript 規(guī)范。當(dāng)然,從 Node.js 8 的 LTS 版本開始,這一提案的內(nèi)容就已經(jīng)有了,我們可以直接進(jìn)入 Node 環(huán)境使用它:
$ node -v v8.9.4 $ node > const obj = { foo: 1, bar: 1 }; undefined > ({ ...obj, baz: 1 }); { foo: 1, bar: 1, baz: 1 }
Object spread operator,即對象展開運(yùn)算符 { ...obj } 和 Object.assign() 的功能是很相似的,那我們應(yīng)該用哪個(gè),它們有什么區(qū)別呢?
Object spread 概況對象展開運(yùn)算符本質(zhì)上是創(chuàng)建一個(gè)新的由現(xiàn)有對象的 own property 組成的普通對象。什么是 own property?一部分是 Object.getOwnPropertyNames() 返回的屬性。那 Object.getOwnPropertyNames() 返回的是什么屬性?它返回的是對象中所有的、包括不可枚舉屬性的、排除 Symbol 在外的的屬性。另一部分就是 Symbol 類型的屬性,也就是 Object.getOwnPropertySymbols() 返回的屬性。
因此,{ ...obj }返回的就是和 obj 所包含的屬性和值相同的對象。
const obj = { foo: "bar" }; const clone = { ...obj }; // `{ foo: "bar" }` obj.foo = "baz"; clone.foo; // "bar"
和 Object.assign() 一樣,對象展開運(yùn)算符同樣不復(fù)制繼承來的屬性和類本身的信息(因?yàn)樗鼈儝煸谠蜕希?,且?huì)復(fù)制 ES6 的 Symbol 類型:
class BaseClass { foo() { return 1; } } class MyClass extends BaseClass { bar() { return 2; } } const obj = new MyClass(); obj.baz = function() { return 3; }; obj[Symbol.for("test")] = 4; // Does _not_ copy any properties from `MyClass` or `BaseClass` const clone = { ...obj }; console.log(clone); // { baz: [Function], [Symbol(test)]: 4 } console.log(clone.constructor.name); // Object console.log(clone instanceof MyClass); // false
這就很清楚了,Object spread 把繼承關(guān)系一概丟掉,類相關(guān)信息一概丟掉,只留著普通對象的屬性,可不可枚舉都有,Symbol 也有。
我們還可以利用對象展開運(yùn)算符來混合屬性,當(dāng)然這里就很簡單了,受順序影響會(huì)產(chǎn)生覆蓋行為:
const obj = { a: "a", b: "b", c: "c" }; { a: 1, b: null, c: void 0, ...obj }; // { a: "a", b: "b", c: "c" } { a: 1, b: null, ...obj, c: void 0 }; // { a: "a", b: "b", c: undefined } { a: 1, ...obj, b: null, c: void 0 }; // { a: "a", b: null, c: undefined } { ...obj, a: 1, b: null, c: void 0 }; // { a: 1, b: null, c: undefined }差異對比
上述的例子里,這兩者其實(shí)沒什么區(qū)別。事實(shí)上這倆操作可以寫個(gè)等式:
{ ...obj } === Object.assign({}, obj) // 這個(gè)等式是開玩笑的!
因此有:
const obj = { a: "a", b: "b", c: "c" }; Object.assign({ a: 1, b: null, c: void 0 }, obj); // { a: "a", b: "b", c: "c" } Object.assign({ a: 1, b: null }, obj, { c: void 0 }); // { a: "a", b: "b", c: undefined } Object.assign({ a: 1 }, obj, { b: null, c: void 0 }); // { a: "a", b: null, c: undefined } Object.assign({}, obj, { a: 1, b: null, c: void 0 }); // { a: 1, b: null, c: undefined }
那么問題來了,既然沒啥區(qū)別,我干嘛要用一個(gè)而不是另一個(gè)?
行為差異之一也是大家一般都知道的點(diǎn)是,對象展開運(yùn)算符總是會(huì)返回一個(gè) POJO(Plain Old Java Object) 對象,而 Object.assign() 如果將原對象作為第一個(gè)參數(shù)傳入,原對象會(huì)被修改:
class MyClass { set val(v) { console.log("Setter called", v); return v; } } const obj = new MyClass(); Object.assign(obj, { val: 42 }); // Prints "Setter called 42"
換句話講,Object.assign() 會(huì)修改第一個(gè)參數(shù)的對象,并且會(huì)觸發(fā) ES6 setter。因此,如果我們更希望使用 Immutable 技術(shù),自然要配置一下用上 object spread。這也是為什么,很多時(shí)候我們用 Object.assign() 的方式就是第一個(gè)參數(shù)置為空對象:
const copyOne = Object.assign({}, obj);性能
總的來說,如果我們向 Object.assign() 的第一個(gè)參數(shù)傳入 {},那么對象展開運(yùn)算符更快,否則基本差不多。
我們來使用 benchmark.js 對其進(jìn)行評估:
const Benchmark = require("benchmark"); const suite = new Benchmark.Suite; const obj = { foo: 1, bar: 2 }; suite. add("Object spread", function() { ({ baz: 3, ...obj }); }). add("Object.assign()", function() { Object.assign({ baz: 3 }, obj); }). on("cycle", function(event) { console.log(String(event.target)); }). on("complete", function() { console.log("Fastest is " + this.filter("fastest").map("name")); }). run({ "async": true });
這種場景下,而這差別不大:
Object spread x 3,170,111 ops/sec +-1.50% (90 runs sampled)
Object.assign() x 3,290,165 ops/sec +-1.86% (88 runs sampled)
Fastest is Object.assign()
但如果向 Object.assign() 的第一個(gè)參數(shù)傳入 {},對象展開運(yùn)算符就總是更快了:
suite. add("Object spread", function() { ({ baz: 3, ...obj }); }). add("Object.assign()", function() { Object.assign({}, obj, { baz: 3 }); })
得到結(jié)果為:
Object spread x 3,065,831 ops/sec +-2.12% (85 runs sampled)總結(jié)
Object.assign() x 2,461,926 ops/sec +-1.52% (88 runs sampled)
Fastest is Object spread
行為上,Object.assign() 可以修改第一個(gè)參數(shù)傳入的對象,觸發(fā) ES6 setter
性能上,當(dāng)Object.assign() 的第一個(gè)參數(shù)傳入 {},{ ...obj } 更快
New in Chrome 72在 Chrome 72 中新增支持如下:
創(chuàng)建類的共有域變得更加簡潔
新的 User Activation API 可以幫助我們知道一個(gè)頁面是否被「激活」
Intl.format() API 可以幫助我們更簡單的定位列表
當(dāng)然,第一條我們曾經(jīng)提到過,而第二第三條我沒有了解過。
Public class fields現(xiàn)在我們不再需要在 constructor 中聲明,只需要直接在類定義中聲明類的共有域即可。主要的使用就是通過下劃線來表明其域的身份,然后可以通過 getter、setter 來操作。
class Counter { _value = 0; get value() { return this._value; } increment() { this._value++; } } const counter = new Counter(); console.log(counter.value); // → 0 counter.increment(); console.log(counter.value); // → 1
對私有域的支持以及在開發(fā)中了。當(dāng)然如果 Babel 動(dòng)作更快的話,就又可以先用上了。
User Activation API我們可能都遇到過頁面加載好就自動(dòng)播放音樂的場景,然后被嚇一跳,趕緊找個(gè)靜音鍵或者把 tab 關(guān)掉。這就是為什么一些 API 需要通過用戶的某種操作觸發(fā)后才起作用。不過不同瀏覽器對這個(gè)觸發(fā)的操作的處理并不相同。
Chrome 72 引入了 User Activation v2,它對所有這類 API 進(jìn)行了簡化。v2 基于新的標(biāo)準(zhǔn),為了能夠使所有瀏覽器標(biāo)準(zhǔn)化。
新的 userActivation 屬性掛在了 navigator 和 MessageEvent 上:hasBeenActive 和 isActive。
hasBeenActive 表明關(guān)聯(lián)的窗口是否在其周期內(nèi)見到了 user activation
isActive 表明關(guān)聯(lián)的窗口是否已經(jīng)觸發(fā)了 user activation
這一點(diǎn)沒了解過,略有些不理解??聪逻@個(gè)圖吧,圖為用戶觸發(fā) User activation API 之前和之后的變化。
Localizing lists of things with Intl.format用我們想用的語言初始化,然后調(diào)用 format 方法,它就會(huì)使用正確的詞語和語法。例如下面的例子是將列表中的單詞拼接起來,并且按照指定的語言(fr,指法語),補(bǔ)充了相應(yīng)語言的「and 與」及「or 或」的單詞。這部分操作都會(huì)交給 JS 引擎而不會(huì)犧牲性能。如下就是將一些動(dòng)物名詞用 or 來拼接:
const opts = {type: "disjunction"}; const lf = new Intl.ListFormat("fr", opts); lf.format(["chien", "chat", "oiseau"]); // → "chien, chat ou oiseau" 意思是「狗、貓或鳥」 lf.format(["chien", "chat", "oiseau", "lapin"]); // → "chien, chat, oiseau ou lapin" 意思是「狗、貓、鳥或兔子」
源地址:https://developers.google.com...
New JavaScript features in ES2019Chrome 73 默認(rèn)支持這些 ES2019 特性,因此今天來盤一部分新特性。
Array#{flat,flatMap}:Array.prototype.flat,一開始提案為 Array.prototype.flatten,其作用就是遞歸的將數(shù)組展平到指定深度,默認(rèn)深度為 1。這個(gè)方法感覺像過去被問過的題。
// Flatten one level: const array = [1, [2, [3]]]; array.flat(); // → [1, 2, [3]] // Flatten recursively until the array contains no more nested arrays: array.flat(Infinity); // → [1, 2, 3]
提案還包括 Array.prototype.flatMap,它會(huì)把數(shù)組再展成新的數(shù)組。
[2, 3, 4].flatMap((x) => [x, x * 2]); // → [2, 4, 3, 6, 4, 8]
源地址:https://developers.google.com...
Object.fromEntries:Object.fromEntries 是針對 Object.entries 的補(bǔ)充,基本可以理解成 Object.fromEntries(Object.entries(object)) ≈ object。
const object = { x: 42, y: 50 }; const entries = Object.entries(object); // [["x", 42], ["y", 50]] const result = Object.fromEntries(entries); // { x: 42, y: 50 }
源地址:https://github.com/tc39/propo...
String#{trimStart,trimEnd}:除了已有的 String.prototype.trim(),V8 現(xiàn)在實(shí)現(xiàn)了 String.prototype.trimStart() 和 String.prototype.trimEnd()。過去這倆功能有非標(biāo)準(zhǔn)的 trimLeft() 和 trimRight()。
const string = " hello world "; string.trimStart(); // → "hello world " string.trimEnd(); // → " hello world" string.trim(); // → "hello world"
源地址:https://v8.dev/blog/v8-releas...
Symbol#description:Symbol.prototype.description 提案在 stage 4,所以也是 ES2019 中的內(nèi)容。
當(dāng)我們通過工廠函數(shù) Symbol() 創(chuàng)建了一個(gè) symbol 的時(shí)候,我們可以選擇傳入一個(gè)字符串作為說明:
const sym = Symbol("The description");
過去我們想要使用這個(gè)說明的方法是通過 String:
assert.equal(String(sym), "Symbol(The description)");
現(xiàn)在提案引入了 Symbol.prototype.description,我們可以通過原型鏈上的屬性來訪問:
assert.equal(sym.description, "The description");
源地址:http://2ality.com/2019/01/sym...
try {} catch {} // optional binding:這一條說的是 try-catch 可以不強(qiáng)制使用參數(shù)了,也就是 err。
try { doSomethingThatMightThrow(); } catch { // no binding! handleException(); }stable Array#sort:
過去 V8 對于超過 10 個(gè)元素的數(shù)組使用的是不穩(wěn)定的快排,現(xiàn)在使用的是穩(wěn)定的 TimSort 算法。
源地址:https://twitter.com/mathias/s...
iOS 12.2 Beta"s 支持 Web Share APIiOS 12.2 beta 版在 Safari 和其他 web 視圖里引入了 Web Share API。這說明什么呢?我們可以通過在頁面上創(chuàng)建一個(gè)按鈕,而這個(gè)按鈕可以觸發(fā)原生系統(tǒng)拉起「share sheet」。
具體是什么樣的呢?我們可以看下官方 Demo,頁面如下:
可以看下這個(gè) Demo 的源碼,核心部分就是下面這句:
try { await navigator.share({ title, text, url }); } catch (error) { logError("Error sharing: " + error); return; }
所以這里我們可以做些能力檢測,再?zèng)Q定是否調(diào)用:
if (navigator.share === undefined) { logError("Error: You need to use a browser that supports this draft proposal."); }
其效果就是拉起「share sheet」,放張圖就知道了(當(dāng)然這里并沒有升系統(tǒng)版本,但喚起的 share sheet 就是圖中所示):
補(bǔ)充:Web Share API 文檔見這里。
Yarn"s Future - v2 and beyond今天看下 Ma?l Nison 關(guān)于 Yarn 未來的展望。嗯,大佬終究是大佬,發(fā)量果然還可以。
Yarn 將成為一個(gè)開發(fā)優(yōu)先的工具這話我們已經(jīng)說了一段時(shí)間了,但是現(xiàn)在我們已經(jīng)準(zhǔn)備好開始了。包管理器不是應(yīng)該在生產(chǎn)服務(wù)器上運(yùn)行的工具。在那里運(yùn)行的代碼越多,出現(xiàn)問題的可能性就越高,最終會(huì)導(dǎo)致生產(chǎn)系統(tǒng)崩潰。Yarn 的開發(fā)優(yōu)先意味著我們將使您能夠做到像是克隆存儲(chǔ)庫的狀態(tài)。這包括重點(diǎn)使用 Plug"n"Play。
Yarn 將使用 TypeScript 重寫Yarn 已經(jīng)完全被 Flow 類型覆蓋,而且運(yùn)作的非常不錯(cuò)。我們希望讓第三方貢獻(xiàn)者盡可能輕松地進(jìn)行 shim 并幫助我們維護(hù)這個(gè)非常棒的工具,所以我們將代碼切換為 TypeScript 實(shí)現(xiàn)。我們希望這有助于使代碼庫比您已經(jīng)貢獻(xiàn)的項(xiàng)目更熟悉。
Yarn 會(huì)成為一個(gè) API,內(nèi)部組件可以被拆分成模塊化實(shí)體這是個(gè)很大的目標(biāo)。目前在使用 Yarn 時(shí),我們唯一的選擇是命令行界面。我們沒有提供允許您利用我們實(shí)現(xiàn)的復(fù)雜邏輯的 primitives -— 無論是解析器、鏈接器還是訪問配置。Yarn 將首先是 API,然后是 CLI。
Yarn 會(huì)支持不同的安裝目標(biāo)而不僅是 Node包管理是一個(gè)總是被不斷推翻重來的難題 - 即使 Yarn 過去也是這樣做的。我們認(rèn)為原因是所有包管理器都需要以稍微不同的方式布置已安裝的包,以便宿主讀取它們。遺憾的是,這很難實(shí)現(xiàn),最終重寫包管理器并丟棄已有的用戶體驗(yàn)和功能反而變得更容易些。從 Berry 開始,我們明確了一個(gè)目標(biāo),即可以切換管道的每個(gè)組件以適應(yīng)不同的安裝目標(biāo)。在某種程度上,Yarn 現(xiàn)在將不僅是包管理器,還要成為包管理器平臺(tái)。如果您仍想使用 Yarn 來對 PHP、Python、Ruby 軟件包進(jìn)行管理,開一個(gè) issue,我們一起來做!
需要的時(shí)候,整體上的兼容性將會(huì)被保留這種 semver-major changes 在設(shè)計(jì)上是不向后兼容的,但我們會(huì)確保將它們保持在可接受的水平,特別是核心命令(yarn install、yarn add、yarn remove、yarn run)將保持相同的行為。先前 yarn.lock將被靜默遷移。一個(gè)重要的警告:我們的安裝現(xiàn)在默認(rèn)使用 Plug"n"Play。在過去的幾個(gè)月里,我們已經(jīng)證明這種方法是合理的,可以解決所有潛在的實(shí)施問題,最后與項(xiàng)目維護(hù)人員討論,以確定是否有任何我們可以做的事情來幫助他們確保一切準(zhǔn)備就緒。現(xiàn)在是時(shí)候冒險(xiǎn)了。
源地址:https://github.com/yarnpkg/ya...
「每日一瞥」是團(tuán)隊(duì)內(nèi)部日常業(yè)界動(dòng)態(tài)提煉,發(fā)布時(shí)效可能略有延后。文章可隨意轉(zhuǎn)載,但請保留此 原文鏈接。
非常歡迎有激情的你加入 ES2049 Studio,簡歷請發(fā)送至 caijun.hcj(at)alibaba-inc.com 。
若有收獲,就賞束稻谷吧
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101784.html
摘要:目前前端主要有以下四種方法會(huì)觸發(fā)對應(yīng)的回調(diào)方法方法客戶端回調(diào)客戶端回調(diào)參考地址每日一瞥是團(tuán)隊(duì)內(nèi)部日常業(yè)界動(dòng)態(tài)提煉,發(fā)布時(shí)效可能略有延后。 showImg(https://segmentfault.com/img/remote/1460000017975436?w=1200&h=630); 「ES2015 - ES2018」Rest / Spread Properties 梳理 Thr...
摘要:當(dāng)引擎開始執(zhí)行腳本是的時(shí)候,會(huì)先創(chuàng)建一個(gè)全局執(zhí)行上下文,并將其到當(dāng)前執(zhí)行棧,無論何時(shí)一個(gè)函數(shù)被調(diào)用,就會(huì)創(chuàng)建一個(gè)新的函數(shù)執(zhí)行上下文并壓入棧中。當(dāng)函數(shù)執(zhí)行完畢,執(zhí)行棧會(huì)將其彈出,并把控制權(quán)交給當(dāng)前棧的下一個(gè)上下文。 showImg(https://segmentfault.com/img/remote/1460000017516912?w=1200&h=630); 從過去直到 Reac...
showImg(https://segmentfault.com/img/remote/1460000018793640?w=900&h=500); 簡介 安全、注入攻擊、XSS 13歲女學(xué)生被捕:因發(fā)布 JavaScript 無限循環(huán)代碼。 這條新聞是來自 2019年3月10日 很多同學(xué)匆匆一瞥便滑動(dòng)屏幕去看下一條消息了,并沒有去了解這段代碼是什么,怎么辦才能防止這個(gè)問題。事情發(fā)生后為了抗議日本...
摘要:配置在設(shè)置項(xiàng)中確認(rèn)包含增加設(shè)置項(xiàng),值為一個(gè)字符串路徑,必須以結(jié)尾在模板中這樣引用在的目錄存放靜態(tài)文件開發(fā)期間使用極度低效時(shí)有別的做法注意默認(rèn)為,一個(gè)列表,表示獨(dú)立于的靜態(tài)文件存放位置。 配置 1.在INSTALLED_APPS設(shè)置項(xiàng)中確認(rèn)包含django.contrib.staticfiles 2.增加STATIC_URL設(shè)置項(xiàng),值為一個(gè)字符串(路徑),必須以‘/’結(jié)尾 3.在模板中...
閱讀 2349·2021-11-24 09:39
閱讀 3794·2021-11-19 09:40
閱讀 2166·2021-09-27 13:36
閱讀 1907·2019-08-30 15:44
閱讀 404·2019-08-30 13:52
閱讀 2720·2019-08-30 11:13
閱讀 2202·2019-08-29 16:18
閱讀 1768·2019-08-29 15:43