<meta name="source" content="lake">
比較typeof與instanceof?
相同點(diǎn):JavaScript 中 typeof 和 instanceof 常用來(lái)判斷一個(gè)變量是否為空闲擦,或者是什么類型的。
typeof的定義和用法:返回值是一個(gè)字符串场梆,用來(lái)說(shuō)明變量的數(shù)據(jù)類型墅冷。
細(xì)節(jié):
(1)、typeof 一般只能返回如下幾個(gè)結(jié)果:number,boolean,string,function,object,undefined或油。
(2)寞忿、typeof 來(lái)獲取一個(gè)變量是否存在,如 if(typeof a!="undefined"){alert("ok")}顶岸,而不要去使用 if(a) 因?yàn)槿绻?a 不存在(未聲明)則會(huì)出錯(cuò)腔彰。
(3)叫编、對(duì)于 Array,Null 等特殊對(duì)象使用 typeof 一律返回 object,這正是 typeof 的局限性霹抛。
Instanceof定義和用法:instanceof 用于判斷一個(gè)變量是否屬于某個(gè)對(duì)象的實(shí)例宵溅。
實(shí)例演示:
a instanceof b?alert("true"):alert("false"); //a是b的實(shí)例?真:假
var a = new Array();
alert(a instanceof Array); // true
alert(a instanceof Object) // true
如上上炎,會(huì)返回 true恃逻,同時(shí) alert(a instanceof Object) 也會(huì)返回 true;這是因?yàn)?Array 是 object 的子類。
function test(){};
var a = new test();
alert(a instanceof test) // true
細(xì)節(jié):
(1)藕施、如下寇损,得到的結(jié)果為‘N’,這里的 instanceof 測(cè)試的 object 是指 js 語(yǔ)法中的 object,不是指 dom 模型對(duì)象裳食。
if (window instanceof Object){ alert('Y')} else { alert('N');} // 'N'
如何理解閉包矛市?
1、定義和用法:當(dāng)一個(gè)函數(shù)的返回值是另外一個(gè)函數(shù)诲祸,而返回的那個(gè)函數(shù)如果調(diào)用了其父函數(shù)內(nèi)部的其它變量浊吏,如果返回的這個(gè)函數(shù)在外部被執(zhí)行,就產(chǎn)生了閉包救氯。
2找田、表現(xiàn)形式:使函數(shù)外部能夠調(diào)用函數(shù)內(nèi)部定義的變量。
3着憨、實(shí)例如下:
(1)墩衙、根據(jù)作用域鏈的規(guī)則,底層作用域沒(méi)有聲明的變量甲抖,會(huì)向上一級(jí)找漆改,找到就返回,沒(méi)找到就一直找准谚,直到window的變量挫剑,沒(méi)有就返回undefined。這里明顯count 是函數(shù)內(nèi)部的flag2 的那個(gè)count 柱衔。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> var count=10; //全局作用域 標(biāo)記為flag1 function add(){ var count=0; //函數(shù)全局作用域 標(biāo)記為flag2 return function(){ count+=1; //函數(shù)的內(nèi)部作用域 alert(count); } } var s = add() s();//輸出1 s();//輸出2</pre>
變量的作用域
要理解閉包樊破,首先必須理解Javascript特殊的變量作用域。
變量的作用域分類:全局變量和局部變量秀存。
特點(diǎn):
1捶码、函數(shù)內(nèi)部可以讀取函數(shù)外部的全局變量;在函數(shù)外部無(wú)法讀取函數(shù)內(nèi)的局部變量或链。
2、函數(shù)內(nèi)部聲明變量的時(shí)候档押,一定要使用var命令澳盐。如果不用的話祈纯,你實(shí)際上聲明了一個(gè)全局變量!
5叼耙、使用閉包的注意點(diǎn)
1)濫用閉包腕窥,會(huì)造成內(nèi)存泄漏:由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大筛婉,所以不能濫用閉包簇爆,否則會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露爽撒。解決方法是入蛆,在退出函數(shù)之前,將不使用的局部變量全部刪除硕勿。
2)會(huì)改變父函數(shù)內(nèi)部變量的值哨毁。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用源武,把閉包當(dāng)作它的公用方法(Public Method)扼褪,把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心粱栖,不要隨便改變父函數(shù)內(nèi)部變量的值话浇。
什么是跨域?跨域請(qǐng)求資源的方法有哪些闹究?
1凳枝、什么是跨域?
由于瀏覽器同源策略跋核,凡是發(fā)送請(qǐng)求url的協(xié)議岖瑰、域名、端口三者之間任意一與當(dāng)前頁(yè)面地址不同即為跨域砂代。存在跨域的情況:
網(wǎng)絡(luò)協(xié)議不同峡眶,如http協(xié)議訪問(wèn)https協(xié)議幽纷。
端口不同,如80端口訪問(wèn)8080端口。
域名不同盈魁,如qianduanblog.com訪問(wèn)baidu.com。
子域名不同翩迈,如abc.qianduanblog.com訪問(wèn)def.qianduanblog.com膘流。
域名和域名對(duì)應(yīng)ip,如www.a.com訪問(wèn)20.205.28.90.
2、跨域請(qǐng)求資源的方法:
(1)丁屎、porxy代理
定義和用法:proxy代理用于將請(qǐng)求發(fā)送給后臺(tái)服務(wù)器荠锭,通過(guò)服務(wù)器來(lái)發(fā)送請(qǐng)求,然后將請(qǐng)求的結(jié)果傳遞給前端晨川。
實(shí)現(xiàn)方法:通過(guò)nginx代理证九;
注意點(diǎn):1删豺、如果你代理的是https協(xié)議的請(qǐng)求,那么你的proxy首先需要信任該證書(尤其是自定義證書)或者忽略證書檢查愧怜,否則你的請(qǐng)求無(wú)法成功呀页。
(2)、CORS 【Cross-Origin Resource Sharing】
定義和用法:是現(xiàn)代瀏覽器支持跨域資源請(qǐng)求的一種最常用的方式拥坛。
使用方法:一般需要后端人員在處理請(qǐng)求數(shù)據(jù)的時(shí)候蓬蝶,添加允許跨域的相關(guān)操作。如下:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8", "Access-Control-Allow-Origin":'http://localhost', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type' });</pre>
(3)猜惋、jsonp
定義和用法:通過(guò)動(dòng)態(tài)插入一個(gè)script標(biāo)簽丸氛。瀏覽器對(duì)script的資源引用沒(méi)有同源限制,同時(shí)資源加載到頁(yè)面后會(huì)立即執(zhí)行(沒(méi)有阻塞的情況下)惨奕。
特點(diǎn):通過(guò)情況下雪位,通過(guò)動(dòng)態(tài)創(chuàng)建script來(lái)讀取他域的動(dòng)態(tài)資源,獲取的數(shù)據(jù)一般為json格式梨撞。
實(shí)例如下:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> <script> function testjsonp(data) { console.log(data.name); // 獲取返回的結(jié)果 } </script> <script> var _script = document.createElement('script'); _script.type = "text/javascript"; _script.src = "http://localhost:8888/jsonp?callback=testjsonp"; document.head.appendChild(_script); </script></pre>
缺點(diǎn):
1雹洗、這種方式無(wú)法發(fā)送post請(qǐng)求(這里)
2、另外要確定jsonp的請(qǐng)求是否失敗并不容易卧波,大多數(shù)框架的實(shí)現(xiàn)都是結(jié)合超時(shí)時(shí)間來(lái)判定时肿。
談?wù)劺厥諜C(jī)制方式及內(nèi)存管理
回收機(jī)制方式
1、定義和用法:垃圾回收機(jī)制(GC:Garbage Collection),執(zhí)行環(huán)境負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存港粱。
2螃成、原理:垃圾收集器會(huì)定期(周期性)找出那些不在繼續(xù)使用的變量,然后釋放其內(nèi)存查坪。但是這個(gè)過(guò)程不是實(shí)時(shí)的寸宏,因?yàn)槠溟_(kāi)銷比較大,所以垃圾回收器會(huì)按照固定的時(shí)間間隔周期性的執(zhí)行偿曙。
3氮凝、實(shí)例如下:
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> function fn1() { var obj = {name: 'hanzichi', age: 10}; } function fn2() { var obj = {name:'hanzichi', age: 10}; return obj; } var a = fn1(); var b = fn2();</pre>
fn1中定義的obj為局部變量,而當(dāng)調(diào)用結(jié)束后望忆,出了fn1的環(huán)境罩阵,那么該塊內(nèi)存會(huì)被js引擎中的垃圾回收器自動(dòng)釋放;在fn2被調(diào)用的過(guò)程中启摄,返回的對(duì)象被全局變量b所指向稿壁,所以該塊內(nèi)存并不會(huì)被釋放。
請(qǐng)說(shuō)出三種減低頁(yè)面加載時(shí)間的方法
壓縮css歉备、js文件
合并js傅是、css文件,減少http請(qǐng)求
外部js、css文件放在最底下
減少dom操作落午,盡可能用變量替代不必要的dom操作
web前端開(kāi)發(fā)谎懦,如何提高頁(yè)面性能優(yōu)化肚豺?
內(nèi)容方面:
1.減少 HTTP 請(qǐng)求 (Make Fewer HTTP Requests)
2.減少 DOM 元素?cái)?shù)量 (Reduce the Number of DOM Elements)
3.使得 Ajax 可緩存 (Make Ajax Cacheable)
針對(duì)CSS:
1.把 CSS 放到代碼頁(yè)上端 (Put Stylesheets at the Top)
2.從頁(yè)面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
3.精簡(jiǎn) JavaScript 與 CSS (Minify JavaScript and CSS)
4.避免 CSS 表達(dá)式 (Avoid CSS Expressions)
針對(duì)JavaScript :
\1. 腳本放到 HTML 代碼頁(yè)底部 (Put Scripts at the Bottom)
\2. 從頁(yè)面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
\3. 精簡(jiǎn) JavaScript 與 CSS (Minify JavaScript and CSS)
\4. 移除重復(fù)腳本 (Remove Duplicate Scripts)
面向圖片(Image):
1.優(yōu)化圖片
2 不要在 HTML 中使用縮放圖片
3 使用恰當(dāng)?shù)膱D片格式
4 使用 CSS Sprites 技巧對(duì)圖片優(yōu)化
瀏覽器是如何渲染頁(yè)面的溃斋?
渲染的流程如下:
1.解析HTML文件,創(chuàng)建DOM樹(shù)吸申。
自上而下梗劫,遇到任何樣式(link、style)與腳本(script)都會(huì)阻塞(外部樣式不阻塞后續(xù)外部腳本的加載)截碴。
2.解析CSS梳侨。優(yōu)先級(jí):瀏覽器默認(rèn)設(shè)置<用戶設(shè)置<外部樣式<內(nèi)聯(lián)樣式<HTML中的style樣式;
3.將CSS與DOM合并日丹,構(gòu)建渲染樹(shù)(Render Tree)
4.布局和繪制走哺,重繪(repaint)和重排(reflow)
Controlled Component 與 Uncontrolled Component 之間的區(qū)別是什么?
React 的核心組成之一就是能夠維持內(nèi)部狀態(tài)的自治組件哲虾,不過(guò)當(dāng)我們引入原生的HTML表單元素時(shí)(input,select,textarea 等)丙躏,我們是否應(yīng)該將所有的數(shù)據(jù)托管到 React 組件中還是將其仍然保留在 DOM 元素中呢?這個(gè)問(wèn)題的答案就是受控組件與非受控組件的定義分割束凑。受控組件(Controlled Component)代指那些交由 React 控制并且所有的表單數(shù)據(jù)統(tǒng)一存放的組件晒旅。譬如下面這段代碼中username
變量值并沒(méi)有存放到DOM元素中,而是存放在組件狀態(tài)數(shù)據(jù)中汪诉。任何時(shí)候我們需要改變username
變量值時(shí)废恋,我們應(yīng)當(dāng)調(diào)用setState
函數(shù)進(jìn)行修改。
JavaScript
<colgroup><col width="375"><col width="375"></colgroup>
|
12345678910111213141516171819202122
|
class ControlledForm extends Component { state = { username: '' } updateUsername = (e) => { this.setState({ username: e.target.value, }) } handleSubmit = () => {} render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' value={this.state.username} onChange={this.updateUsername} /> <button type='submit'>Submit</button> </form> ) }}
|
| | |
而非受控組件(Uncontrolled Component)則是由DOM存放表單數(shù)據(jù)扒寄,并非存放在 React 組件中鱼鼓。我們可以使用 refs 來(lái)操控DOM元素:
JavaScript
<colgroup><col width="375"><col width="375"></colgroup>
|
123456789101112131415
|
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) }}
|
| | |
竟然非受控組件看上去更好實(shí)現(xiàn),我們可以直接從 DOM 中抓取數(shù)據(jù)该编,而不需要添加額外的代碼迄本。不過(guò)實(shí)際開(kāi)發(fā)中我們并不提倡使用非受控組件,因?yàn)閷?shí)際情況下我們需要更多的考慮表單驗(yàn)證上渴、選擇性的開(kāi)啟或者關(guān)閉按鈕點(diǎn)擊岸梨、強(qiáng)制輸入格式等功能支持,而此時(shí)我們將數(shù)據(jù)托管到 React 中有助于我們更好地以聲明式的方式完成這些功能稠氮。引入 React 或者其他 MVVM 框架最初的原因就是為了將我們從繁重的直接操作 DOM 中解放出來(lái)曹阔。
什么是 React 的 refs ,為什么它們很重要隔披?
refs就像是一個(gè)逃生艙口赃份,允許您直接訪問(wèn)DOM元素或組件實(shí)例。為了使用它們,您可以向組件添加一個(gè) ref 屬性抓韩,該屬性的值是一個(gè)回調(diào)函數(shù)纠永,它將接收底層的 DOM 元素或組件的已掛接實(shí)例,作為其第一個(gè)參數(shù)谒拴。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) } }</pre>
以上注意到我們的輸入字段有一個(gè) ref 屬性尝江,其值是一個(gè)函數(shù)。該函數(shù)接收我們?nèi)缓蠓旁趯?shí)例上的實(shí)際的 DOM 元素英上,以便在 handleSubmit 函數(shù)內(nèi)部訪問(wèn)它炭序。經(jīng)常誤解的是,您需要使用類組件才能使用 ref 苍日,但 ref 也可以通過(guò)利用 JavaScript
中的 閉包 與 功能組件( functional components )一起使用惭聂。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> function CustomForm ({handleSubmit}) { let inputElement return ( <form onSubmit={() => handleSubmit(inputElement.value)}> <input type='text' ref={(input) => inputElement = input} /> <button type='submit'>Submit</button> </form> ) }</pre>
React 中的keys是什么,為什么它們很重要相恃?
keys是什么幫助 React 跟蹤哪些項(xiàng)目已更改辜纲、添加或從列表中刪除。
<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"> return ( <ul> {this.state.todoItems.map(({task, uid}) => { return <li key={uid}>{task}</li> })} </ul> ) }</pre>
每個(gè) keys 在兄弟元素之間是獨(dú)一無(wú)二的拦耐。我們已經(jīng)談過(guò)幾次關(guān)于和解(reconciliation)的過(guò)程耕腾,而且這個(gè)和解過(guò)程(reconciliation)中的一部分正在執(zhí)行一個(gè)新的元素樹(shù)與最前一個(gè)的差異。keys 使處理列表時(shí)更加高效揩魂,因?yàn)?React 可以使用子元素上的 keys 快速知道元素是新的還是在比較樹(shù)時(shí)才被移動(dòng)幽邓。
而且 keys 不僅使這個(gè)過(guò)程更有效率,而且沒(méi)有 keys 火脉,React 不知道哪個(gè)本地狀態(tài)對(duì)應(yīng)于移動(dòng)中的哪個(gè)項(xiàng)目牵舵。所以當(dāng)你 map 的時(shí)候,不要忽略了 keys 倦挂。
在哪個(gè)生命周期事件中你會(huì)發(fā)出 AJAX 請(qǐng)求畸颅,為什么?
AJAX 請(qǐng)求應(yīng)該在 componentDidMount
生命周期事件中方援。 有幾個(gè)原因:
- Fiber没炒,是下一次實(shí)施React的和解算法,將有能力根據(jù)需要啟動(dòng)和停止渲染犯戏,以獲得性能優(yōu)勢(shì)送火。其中一個(gè)取舍之一是
componentWillMount
,而在其他的生命周期事件中出發(fā) AJAX 請(qǐng)求先匪,將是具有 “非確定性的”种吸。 這意味著 React 可以在需要時(shí)感覺(jué)到不同的時(shí)間開(kāi)始調(diào)用 componentWillMount。這顯然是AJAX請(qǐng)求的不好的方式呀非。
-您不能保證在組件掛載之前坚俗,AJAX請(qǐng)求將無(wú)法 resolve镜盯。如果這樣做,那意味著你會(huì)嘗試在一個(gè)未掛載的組件上設(shè)置 StState猖败,這不僅不會(huì)起作用速缆,反而會(huì)對(duì)你大喊大叫。 在 componentDidMount
中執(zhí)行 AJAX 將保證至少有一個(gè)要更新的組件恩闻。