1 閉包
閉包就是能夠讀取其他函數內部變量的函數
閉包是指有權訪問另一個函數作用域中變量的函數,創建閉包的最常見的方式就是在一個函數內創建另一個函數,通過另一個函數訪問這個函數的局部變量,利用閉包可以突破作用鏈域
閉包的特性:
函數內再嵌套函數
內部函數可以引用外層的參數和變量
參數和變量不會被垃圾回收機制回收
說說你對閉包的理解
使用閉包主要是為了設計私有的方法和變量。閉包的優點是可以避免全局變量的污染,缺點是閉包會常駐內存,會增大內存使用量,使用不當很容易造成內存泄露。在js中,函數即閉包,只有函數才會產生作用域的概念
閉包 的最大用處有兩個,一個是可以讀取函數內部的變量,另一個就是讓這些變量始終保持在內存中
閉包的另一個用處,是封裝對象的私有屬性和私有方法
好處:能夠實現封裝和緩存等;
壞處:就是消耗內存、不正當使用會造成內存溢出的問題
使用閉包的注意點
由于閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露
解決方法是,在退出函數之前,將不使用的局部變量全部刪除
2 說說你對作用域鏈的理解
作用域鏈的作用是保證執行環境里有權訪問的變量和函數是有序的,作用域鏈的變量只能向上訪問,變量訪問到window對象即被終止,作用域鏈向下訪問變量是不被允許的
簡單的說,作用域就是變量與函數的可訪問范圍,即作用域控制著變量與函數的可見性和生命周期
3 JavaScript原型,原型鏈 ? 有什么特點?
每個對象都會在其內部初始化一個屬性,就是prototype(原型),當我們訪問一個對象的屬性時
如果這個對象內部不存在這個屬性,那么他就會去prototype里找這個屬性,這個prototype又會有自己的prototype,于是就這樣一直找下去,也就是我們平時所說的原型鏈的概念
關系:instance.constructor.prototype = instance.__proto__
特點:
JavaScript對象是通過引用來傳遞的,我們創建的每個新對象實體中并沒有一份屬于自己的原型副本。當我們修改原型時,與之相關的對象也會繼承這一改變
當我們需要一個屬性的時,Javascript引擎會先看當前對象中是否有這個屬性, 如果沒有的
就會查找他的Prototype對象是否有這個屬性,如此遞推下去,一直檢索到Object內建對象
4 請解釋什么是事件代理
事件代理(Event Delegation),又稱之為事件委托。是JavaScript中常用綁定事件的常用技巧。顧名思義,“事件代理”即是把原本需要綁定的事件委托給父元素,讓父元素擔當事件監聽的職務。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好處是可以提高性能
可以大量節省內存占用,減少事件注冊,比如在table上代理所有td的click事件就非常棒
可以實現當新增子對象時無需再次對其綁定
5 Javascript如何實現繼承?
構造繼承
原型繼承
實例繼承
拷貝繼承
原型prototype機制或apply和call方法去實現較簡單,建議使用構造函數與原型混合方式
functionParent(){this.name?='wang';}functionChild(){this.age?=28;}????Child.prototype?=newParent();//繼承了Parent,通過原型var?demo?=?new?Child();alert(demo.age);alert(demo.name);//得到被繼承的屬性
6 談談This對象的理解
this總是指向函數的直接調用者(而非間接調用者)
如果有new關鍵字,this指向new出來的那個對象
在事件中,this指向觸發這個事件的對象,特殊的是,IE中的attachEvent中的this總是指向全局對象Window
W3C中定義事件的發生經歷三個階段:捕獲階段(capturing)、目標階段(targetin)、冒泡階段(bubbling)
冒泡型事件:當你使用事件冒泡時,子級元素先觸發,父級元素后觸發
捕獲型事件:當你使用事件捕獲時,父級元素先觸發,子級元素后觸發
DOM事件流:同時支持兩種事件模型:捕獲型事件和冒泡型事件
阻止冒泡:在W3c中,使用stopPropagation()方法;在IE下設置cancelBubble = true
阻止捕獲:阻止事件的默認行為,例如click - <a>后的跳轉。在W3c中,使用preventDefault()方法,在IE下設置window.event.returnValue = false
創建一個空對象,并且this變量引用該對象,同時還繼承了該函數的原型
屬性和方法被加入到this引用的對象中
新創建的對象由this所引用,并且最后隱式的返回this
Ajax的原理簡單來說是在用戶和服務器之間加了—個中間層(AJAX引擎),通過XmlHttpRequest對象來向服務器發異步請求,從服務器獲得數據,然后用javascript來操作DOM而更新頁面。使用戶操作與服務器響應異步化。這其中最關鍵的一步就是從服務器獲得請求數據
Ajax的過程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心機制
/**?1.?創建連接?**/varxhr?=null;xhr?=newXMLHttpRequest()/**?2.?連接服務器?**/xhr.open('get',?url,true)/**?3.?發送請求?**/xhr.send(null);/**?4.?接受請求?**/xhr.onreadystatechange?=function(){if(xhr.readyState?==4){if(xhr.status?==200){?success(xhr.responseText);?}else{/**?false?**/fail?&&?fail(xhr.status);?}?}}
ajax 有那些優缺點?
優點:
通過異步模式,提升了用戶體驗.
優化了瀏覽器和服務器之間的傳輸,減少不必要的數據往返,減少了帶寬占用.
Ajax在客戶端運行,承擔了一部分本來由服務器承擔的工作,減少了大用戶量下的服務器負載。
Ajax可以實現動態不刷新(局部刷新)
缺點:
安全問題AJAX暴露了與服務器交互的細節。
對搜索引擎的支持比較弱。
不容易調試。
首先了解下瀏覽器的同源策略 同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源
那么怎樣解決跨域問題的呢?
通過jsonp跨域
varscript?=document.createElement('script');script.type?='text/javascript';//?傳參并指定回調執行函數為onBackscript.src?=?'http://www.....:8080/login?user=admin&callback=onBack';document.head.appendChild(script);//?回調執行函數function?onBack(res)?{alert(JSON.stringify(res));}
document.domain + iframe跨域
此方案僅限主域相同,子域不同的跨域應用場景
1.)父窗口:(http://www.domain.com/a.html)
document.domain?='domain.com';varuser?='admin';
2.)子窗口:(http://child.domain.com/b.html)
document.domain?='domain.com';//獲取父窗口中變量alert('get?js?data?from?parent?--->?'+window.parent.user);
nginx代理跨域
nodejs中間件代理跨域
后端在頭部信息里面設置安全域名
立即執行函數,不暴露私有成員
varmodule1?=?(function(){var_count?=0;varm1?=function(){//... }; var?m2?=?function(){ //... }; return?{ m1?:?m1, m2?:?m2};})();
defer,只支持IE
async:
創建script,插入到DOM中,加載完畢后callBack
內存泄漏指任何對象在您不再擁有或需要它之后仍然存在
setTimeout的第一個參數使用字符串而非函數的話,會引發內存泄漏
閉包使用不當
數據體積方面
JSON相對于XML來講,數據的體積小,傳遞的速度更快些。
數據交互方面
JSON與JavaScript的交互更加方便,更容易解析處理,更好的數據交互
數據描述方面
JSON對數據的描述性比XML較差
傳輸速度方面
JSON的速度要遠遠快于XML
WebPack是一個模塊打包工具,你可以使用WebPack管理你的模塊依賴,并編繹輸出模塊們所需的靜態文件。它能夠很好地管理、打包Web開發中所用到的HTML、Javascript、CSS以及各種靜態文件(圖片、字體等),讓開發過程更加高效。對于不同類型的資源,webpack有對應的模塊加載器。webpack模塊打包器會分析模塊間的依賴關系,最后 生成了優化且合并后的靜態資源
CommonJS是服務器端模塊的規范,Node.js采用了這個規范。CommonJS規范加載模塊是同步的,也就是說,只有加載完成,才能執行后面的操作。AMD規范則是非同步加載模塊,允許指定回調函數
AMD推薦的風格通過返回一個對象做為模塊對象,CommonJS的風格通過對module.exports或exports的屬性賦值來達到暴露模塊對象的目的
sql注入原理
就是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令
總的來說有以下幾點
永遠不要信任用戶的輸入,要對用戶的輸入進行校驗,可以通過正則表達式,或限制長度,對單引號和雙"-"進行轉換等
永遠不要使用動態拼裝SQL,可以使用參數化的SQL或者直接使用存儲過程進行數據查詢存取
永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接
不要把機密信息明文存放,請加密或者hash掉密碼和敏感的信息
XSS原理及防范
Xss(cross-site scripting)攻擊指的是攻擊者往Web頁面里插入惡意html標簽或者javascript代碼。比如:攻擊者在論壇中放一個看似安全的鏈接,騙取用戶點擊后,竊取cookie中的用戶私密信息;或者攻擊者在論壇中加一個惡意表單,當用戶提交表單的時候,卻把信息傳送到攻擊者的服務器中,而不是用戶原本以為的信任站點
XSS防范方法
首先代碼里對用戶輸入的地方和變量都需要仔細檢查長度和對”<”,”>”,”;”,”’”等字符做過濾;其次任何內容寫到頁面之前都必須加以encode,避免不小心把html tag弄出來。這一個層面做好,至少可以堵住超過一半的XSS 攻擊
XSS與CSRF有什么區別嗎?
XSS是獲取信息,不需要提前知道其他用戶頁面的代碼和數據包。CSRF是代替用戶完成指定的動作,需要知道其他用戶頁面的代碼和數據包。要完成一次CSRF攻擊,受害者必須依次完成兩個步驟
登錄受信任網站A,并在本地生成Cookie
在不登出A的情況下,訪問危險網站B
CSRF的防御
服務端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加偽隨機數
通過驗證碼的方法
工廠模式:
工廠模式解決了重復實例化的問題,但還有一個問題,那就是識別問題,因為根本無法
主要好處就是可以消除對象間的耦合,通過使用工程方法而不是new關鍵字
構造函數模式
使用構造函數的方法,即解決了重復實例化的問題,又解決了對象識別的問題,該模式與工廠模式的不同之處在于
直接將屬性和方法賦值給this對象;
同源策略指的是:協議,域名,端口相同,同源策略是一種安全協議
舉例說明:比如一個黑客程序,他利用Iframe把真正的銀行登錄頁面嵌到他的頁面上,當你使用真實的用戶名,密碼登錄時,他的頁面就可以通過Javascript讀取到你的表單中input中的內容,這樣用戶名,密碼就輕松到手了。
20 offsetWidth/offsetHeight,clientWidth/clientHeight與scrollWidth/scrollHeight的區別
offsetWidth/offsetHeight返回值包含content + padding + border,效果與e.getBoundingClientRect()相同
clientWidth/clientHeight返回值只包含content + padding,如果有滾動條,也不包含滾動條
scrollWidth/scrollHeight返回值包含content + padding + 溢出內容的尺寸
對象字面量:var obj = {};
構造函數:var obj = new Object();
Object.create():var obj = Object.create(Object.prototype);
png24位的圖片在iE6瀏覽器上出現背景,解決方案是做成PNG8
瀏覽器默認的margin和padding不同。解決方案是加一個全局的*{margin:0;padding:0;}來統一,,但是全局效率很低,一般是如下這樣解決:
body,ul,li,ol,dl,dt,dd,form,input,h1,h2,h3,h4,h5,h6,p{margin:0;padding:0;}
IE下,event對象有x,y屬性,但是沒有pageX,pageY屬性
Firefox下,event對象有pageX,pageY屬性,但是沒有x,y屬性.
依照Promise/A+的定義,Promise有四種狀態:
pending:初始狀態, 非fulfilled或rejected.
fulfilled:成功的操作.
rejected:失敗的操作.
settled: Promise已被fulfilled或rejected,且不是pending
另外,fulfilled與rejected一起合稱settled
Promise對象用來進行延遲(deferred) 和異步(asynchronous) 計算
Promise 的構造函數
構造一個Promise,最基本的用法如下:
varpromise?=newPromise(function(resolve,?reject){if(...)?{//?succeedresolve(result);????????}else{//?failsreject(Error(errMessage));????????}????});
Promise實例擁有then方法(具有then方法的對象,通常被稱為thenable)。它的使用方法如下:
promise.then(onFulfilled,?onRejected)
接收兩個函數作為參數,一個在fulfilled的時候被調用,一個在rejected的時候被調用,接收參數就是future,onFulfilled對應resolve,onRejected對應reject
jquery源碼封裝在一個匿名函數的自執行環境中,有助于防止變量的全局污染,然后通過傳入window對象參數,可以使window對象作為局部變量使用,好處是當jquery中訪問window對象的時候,就不用將作用域鏈退回到頂層作用域了,從而可以更快的訪問window對象。同樣,傳入undefined參數,可以縮短查找undefined時的作用域鏈
jquery將一些原型屬性和方法封裝在了jquery.prototype中,為了縮短名稱,又賦值給了jquery.fn,這是很形象的寫法
有一些數組或對象的方法經常能使用到,jQuery將其保存為局部變量以提高訪問速度
jquery實現的鏈式調用可以節約代碼,所返回的都是同一個對象,可以提高代碼效率
Vue.js一個用于創建web交互界面的庫,是一個精簡的MVVM。它通過雙向數據綁定把View層和Model層連接了起來。實際的DOM封裝和輸出格式都被抽象為了Directives和Filters
AngularJS是一個比較完善的前端MVVM框架,包含模板,數據雙向綁定,路由,模塊化,服務,依賴注入等所有功能,模板功能強大豐富,自帶了豐富的Angular指令
reactReact僅僅是VIEW層是facebook公司。推出的一個用于構建UI的一個庫,能夠實現服務器端的渲染。用了virtual dom,所以性能很好。
特點:
1、它是一個Javascript運行環境
2、依賴于Chrome V8引擎進行代碼解釋
3、事件驅動
4、非阻塞I/O
5、單進程,單線程
優點:
高并發(最重要的優點)
缺點:
1、只支持單核CPU,不能充分利用CPU
2、可靠性低,一旦代碼某個環節崩潰,整個系統都崩潰
CommonJS是服務器端模塊的規范,Node.js采用了這個規范。CommonJS規范加載模塊是同步的,也就是說,只有加載完成,才能執行后面的操作。AMD規范則是非同步加載模塊,允許指定回調函數
AMD推薦的風格通過返回一個對象做為模塊對象,CommonJS的風格通過對module.exports或exports的屬性賦值來達到暴露模塊對象的目的
es6模塊 CommonJS、AMD、CMD
CommonJS的規范中,每個JavaScript文件就是一個獨立的模塊上下文(module context),在這個上下文中默認創建的屬性都是私有的。也就是說,在一個文件定義的變量(還包括函數和類),都是私有的,對其他文件是不可見的。
CommonJS是同步加載模塊,在瀏覽器中會出現堵塞情況,所以不適用
AMD異步,需要定義回調define方式
es6一個模塊就是一個獨立的文件,該文件內部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量es6還可以導出類、方法,自動適用嚴格模式
內存泄漏指任何對象在您不再擁有或需要它之后仍然存在
setTimeout的第一個參數使用字符串而非函數的話,會引發內存泄漏
閉包、控制臺日志、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)
cookie
session
url重寫
隱藏input
ip地址
Undefined、Null、Boolean、Number、String
Object是JavaScript中所有對象的父對象
數據封裝類對象:Object、Array、Boolean、Number和String
其他對象:Function、Arguments、Math、Date、RegExp、Error
不要在同一行聲明多個變量
請使用===/!==來比較true/false或者數值
使用對象字面量替代new Array這種形式
不要使用全局函數
Switch語句必須帶有default分支
If語句必須使用大括號
for-in循環中的變量 應該使用var關鍵字明確限定作用域,從而避免作用域污
棧:原始數據類型(Undefined,Null,Boolean,Number、String)
堆:引用數據類型(對象、數組和函數)
兩種類型的區別是:存儲位置不同;
原始數據類型直接存儲在棧(stack)中的簡單數據段,占據空間小、大小固定,屬于被頻繁使用數據,所以放入棧中存儲;
引用數據類型存儲在堆(heap)中的對象,占據空間大、大小不固定,如果存儲在棧中,將會影響程序運行的性能;引用數據類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其
在棧中的地址,取得地址后從堆中獲得實體
javascript創建對象簡單的說,無非就是使用內置對象或各種自定義對象,當然還可以用JSON;但寫法有很多種,也能混合使用
對象字面量的方式
person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
用function來模擬無參的構造函數
functionPerson(){}varperson=newPerson();//定義一個function,如果使用new"實例化",該function可以看作是一個Classperson.name="Mark";????????person.age="25";????????person.work=function(){????????alert(person.name+"?hello...");}person.work();
用function來模擬參構造函數來實現(用this關鍵字定義構造的上下文屬性)
functionPet(name,age,hobby){this.name=name;//this作用域:當前對象this.age=age;this.hobby=hobby;this.eat=function(){???????????alert("我叫"+this.name+",我喜歡"+this.hobby+",是個程序員");???????}}varmaidou?=newPet("麥兜",25,"coding");//實例化、創建對象maidou.eat();//調用eat方法
用工廠方式來創建(內置對象)
varwcDog?=newObject();?????wcDog.name="旺財";?????wcDog.age=3;?????wcDog.work=function(){???????alert("我是"+wcDog.name+",汪汪汪......");?????}?????wcDog.work();
用原型方式來創建
functionDog(){}Dog.prototype.name="旺財";Dog.prototype.eat=function(){?alert(this.name+"是個吃貨");}varwangcai?=newDog();wangcai.eat();
用混合方式來創建
functionCar(name,price){this.name=name;this.price=price;}Car.prototype.sell=function(){?alert("我是"+this.name+",我現在賣"+this.price+"萬元");}varcamry?=newCar("凱美瑞",27);camry.sell();
它的功能是把對應的字符串解析成JS代碼并運行
應該避免使用eval,不安全,非常耗性能(2次,一次解析成js語句,一次執行)
由JSON字符串轉換為JSON對象的時候可以用eval,var obj =eval('('+ str +')')
undefined表示不存在這個值。
undefined:是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。當嘗試讀取時會返回undefined
例如變量被聲明了,但沒有賦值時,就等于undefined
null表示一個對象被定義了,值為“空值”
null: 是一個對象(空對象, 沒有任何屬性和方法)
例如作為函數的參數,表示該函數的參數不是對象;
在驗證null時,一定要使用===,因為==無法分別null和undefined
37 ["1", "2", "3"].map(parseInt) 答案是多少
[1, NaN, NaN]因為parseInt需要兩個參數(val, radix),其中radix表示解析時用的基數。
map傳了3個(element, index, array),對應的radix不合法導致解析失敗。
38 javascript 代碼中的"use strict";是什么意思
use strict是一種ECMAscript 5添加的(嚴格)運行模式,這種模式使得 Javascript 在更嚴格的條件下運行,使JS編碼更加規范化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式
它是基于JavaScript的一個子集。數據格式簡單, 易于讀寫, 占用帶寬小
JSON字符串轉換為JSON對象:
varobj?=eval('('+?str?+')');varobj?=?str.parseJSON();varobj?=JSON.parse(str);
JSON對象轉換為JSON字符串:
varlast=obj.toJSONString();varlast=JSON.stringify(obj);
defer和async、動態創建DOM方式(用得最多)、按需異步載入js
同步:瀏覽器訪問服務器請求,用戶看得到頁面刷新,重新發請求,等請求完,頁面刷新,新內容出現,用戶看到新內容,進行下一步操作
異步:瀏覽器訪問服務器請求,用戶正常操作,瀏覽器后端進行請求。等請求完,頁面不刷新,新內容也會出現,用戶看到新內容
漸進增強 :針對低版本瀏覽器進行構建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。
優雅降級 :一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容
defer并行加載js文件,會按照頁面上script標簽的順序執行
async并行加載js文件,下載完成立即執行,不會按照頁面上script標簽的順序執行
變量必須聲明后再使用
函數的參數不能有同名屬性,否則報錯
不能使用with語句
禁止this指向全局對象
attribute是dom元素在文檔中作為html標簽擁有的屬性;
property就是dom元素在js中作為對象擁有的屬性。
對于html的標準屬性來說,attribute和property是同步的,是會自動更新的
但是對于自定義的屬性來說,他們是不同步的
新增模板字符串(為JavaScript提供了簡單的字符串插值功能)
箭頭函數
for-of(用來遍歷數據—例如數組中的值。)
arguments對象可被不定參數和默認參數完美代替。
ES6將promise對象納入規范,提供了原生的Promise對象。
增加了let和const命令,用來聲明變量。
增加了塊級作用域。
let命令實際上就增加了塊級作用域。
還有就是引入module模塊的概念
這個語法糖可以讓有OOP基礎的人更快上手js,至少是一個官方的實現了
但對熟悉js的人來說,這個東西沒啥大影響;一個Object.creat()搞定繼承,比class簡潔清晰的多
面向過程就是分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了
面向對象是把構成問題事務分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為
面向對象是以功能來劃分問題,而不是步驟
基本思想是使用對象,類,繼承,封裝等基本概念來進行程序設計
優點
采用面向對象思想設計的結構,可讀性高,由于繼承的存在,即使改變需求,那么維護也只是在局部模塊,所以維護起來是非常方便和較低成本的
易維護
易擴展
開發工作的重用性、繼承性高,降低重復工作量。
縮短了開發周期
可用性(Usability):產品是否容易上手,用戶能否完成任務,效率如何,以及這過程中用戶的主觀感受可好,是從用戶的角度來看產品的質量。可用性好意味著產品質量高,是企業的核心競爭力
可訪問性(Accessibility):Web內容對于殘障用戶的可閱讀和可理解性
可維護性(Maintainability):一般包含兩個層次,一是當系統出現問題時,快速定位并解決問題的成本,成本低則可維護性好。二是代碼是否容易被人理解,是否容易修改和增強功能。
instanceof方法
instanceof運算符是用來測試一個對象是否在其原型鏈原型構造函數的屬性
vararr?=?[];arrinstanceofArray;//?true
constructor方法
constructor屬性返回對創建此對象的數組函數的引用,就是返回對象相對應的構造函數
vararr?=?[];arr.constructor?==Array;//true
最簡單的方法
這種寫法,是jQuery正在使用的
Object.prototype.toString.call(value)?=='[object?Array]'//?利用這個方法,可以寫一個返回數據類型的方法var?isType?=?function?(obj)?{returnObject.prototype.toString.call(obj).slice(8,-1);}
ES5新增方法isArray()
vara?=newArray(123);varb?=newDate();console.log(Array.isArray(a));//trueconsole.log(Array.isArray(b));?//false
let命令不存在變量提升,如果在let前使用,會導致報錯
如果塊區中存在let和const命令,就會形成封閉作用域
不允許重復聲明,因此,不能在函數內部重新聲明參數
forEach方法,是最基本的方法,就是遍歷與循環,默認有3個傳參:分別是遍歷的數組內容item、數組索引index、和當前遍歷數組Array
map方法,基本用法與forEach一致,但是不同的,它會返回一個新的數組,所以在callback需要有return值,如果沒有,會返回undefined
簡單說,"函數式編程"是一種"編程范式"(programming paradigm),也就是如何編寫程序的方法論
它具有以下特性:閉包和高階函數、惰性計算、遞歸、函數是"第一等公民"、只用"表達式"
函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象
不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤
不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用Rest參數代替
不可以使用yield命令,因此箭頭函數不能用作Generator函數
this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,實際上this的最終指向的是那個調用它的對象
《javascript語言精髓》中大概概括了4種調用方式:
方法調用模式
函數調用模式
構造器調用模式
graphLRA-->B
apply/call調用模式
回調函數
優點:簡單、容易理解
缺點:不利于維護,代碼耦合高
事件監聽(采用時間驅動模式,取決于某個事件是否發生):
優點:容易理解,可以綁定多個事件,每個事件可以指定多個回調函數
缺點:事件驅動型,流程不夠清晰
發布/訂閱(觀察者模式)
類似于事件監聽,但是可以通過‘消息中心’,了解現在有多少發布者,多少訂閱者
Promise對象
優點:可以利用then方法,進行鏈式寫法;可以書寫錯誤時的回調函數;
缺點:編寫和理解,相對比較難
Generator函數
優點:函數體內外的數據交換、錯誤處理機制
缺點:流程管理不方便
async函數
優點:內置執行器、更好的語義、更廣的適用性、返回的是Promise、結構清晰。
缺點:錯誤處理機制
數據類型、運算、對象、Function、繼承、閉包、作用域、原型鏈、事件、RegExp、JSON、Ajax、DOM、BOM、內存泄漏、跨域、異步裝載、模板引擎、前端MVC、路由、模塊化、Canvas、ECMAScript
CSS3的動畫的優點
在性能上會稍微好一些,瀏覽器會對CSS3的動畫做一些優化
代碼相對簡單
缺點
在動畫控制上不夠靈活
兼容性不好
JavaScript的動畫正好彌補了這兩個缺點,控制能力很強,可以單幀的控制、變換,同時寫得好完全可以兼容IE6,并且功能強大。對于一些復雜控制的動畫,使用javascript會比較靠譜。而在實現一些小的交互動效的時候,就多考慮考慮CSS吧
通常我們會用循環的方式來遍歷數組。但是循環是 導致js 性能問題的原因之一。一般我們會采用下幾種方式來進行數組的遍歷
for in循環
for循環
forEach
這里的forEach回調中兩個參數分別為value,index
forEach無法遍歷對象
IE不支持該方法;Firefox和chrome支持
forEach無法使用break,continue跳出循環,且使用return是跳過本次循環
這兩種方法應該非常常見且使用很頻繁。但實際上,這兩種方法都存在性能問題
在方式一中,for-in需要分析出array的每個屬性,這個操作性能開銷很大。用在key已知的數組上是非常不劃算的。所以盡量不要用for-in,除非你不清楚要處理哪些屬性,例如JSON對象這樣的情況
在方式2中,循環每進行一次,就要檢查一下數組長度。讀取屬性(數組長度)要比讀局部變量慢,尤其是當array里存放的都是DOM元素,因為每次讀取都會掃描一遍頁面上的選擇器相關元素,速度會大大降低
gulp是前端開發過程中一種基于流的代碼構建工具,是自動化項目的構建利器;它不僅能對網站資源進行優化,而且在開發過程中很多重復的任務能夠使用正確的工具自動完成
Gulp的核心概念:流
流,簡單來說就是建立在面向對象基礎上的一種抽象的處理數據的工具。在流中,定義了一些處理數據的基本操作,如讀取數據,寫入數據等,程序員是對流進行所有操作的,而不用關心流的另一頭數據的真正流向
gulp正是通過流和代碼優于配置的策略來盡量簡化任務編寫的工作
Gulp的特點:
易于使用:通過代碼優于配置的策略,gulp 讓簡單的任務簡單,復雜的任務可管理
構建快速?利用Node.js流的威力,你可以快速構建項目并減少頻繁的IO操作
易于學習?通過最少的API,掌握gulp毫不費力,構建工作盡在掌握:如同一系列流管道
vue.js則是采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應的監聽回調
1:捕獲階段 ---> 2:目標階段 ---> 3:冒泡階段
document--->target目標 ---->document
由此,addEventListener的第三個參數設置為true和false的區別已經非常清晰了
true表示該元素在事件的“捕獲階段”(由外往內傳遞時)響應事件
false表示該元素在事件的“冒泡階段”(由內向外傳遞時)響應事件
let
允許你聲明一個作用域被限制在塊級中的變量、語句或者表達式
let綁定不受變量提升的約束,這意味著let聲明不會被提升到當前
該變量處于從塊開始到初始化處理的“暫存死區”
var
聲明變量的作用域限制在其聲明位置的上下文中,而非聲明變量總是全局的
由于變量聲明(以及其他聲明)總是在任意代碼執行之前處理的,所以在代碼中的任意位置聲明變量總是等效于在代碼開頭聲明
const
聲明創建一個值的只讀引用 (即指針)
基本數據當值發生改變時,那么其對應的指針也將發生改變,故造成const申明基本數據類型時
再將其值改變時,將會造成報錯, 例如const a = 3;a = 5時 將會報錯
但是如果是復合類型時,如果只改變復合類型的其中某個Value項時, 將還是正常使用
vararr?=?[1,2,3,4,5,6,7,8,9,10];arr.sort(function(){returnMath.random()?-0.5;})console.log(arr);
這道題考察了如何在不卡住頁面的情況下渲染數據,也就是說不能一次性將幾萬條都渲染出來,而應該一次渲染部分DOM,那么就可以通過requestAnimationFrame來每16 ms刷新一次
<!DOCTYPE?html>Document
- 控件
不使用第三方框架
vardomList?=document.getElementsByTagName(‘input’)varcheckBoxList?=?[];varlen?=?domList.length;//緩存到局部變量while(len--)?{//使用while的效率會比for循環更高if(domList[len].type?==?‘checkbox’)?{????? checkBoxList.push(domList[len]);? }?}
創建新節點
createDocumentFragment()????//創建一個DOM片段createElement()???//創建一個具體的元素createTextNode()???//創建一個文本節點
添加、移除、替換、插入
appendChild()??????//添加removeChild()??????//移除replaceChild()??????//替換insertBefore()??????//插入
查找
getElementsByTagName()????//通過標簽名稱getElementsByName()?????//通過元素的Name屬性的值getElementById()????????//通過元素Id,唯一性
正則表達式構造函數var reg=new RegExp(“xxx”)與正則表達字面量var reg=//有什么不同?匹配郵箱的正則表達式?
當使用RegExp()構造函數的時候,不僅需要轉義引號(即\”表示”),并且還需要雙反斜杠(即\\表示一個\)。使用正則表達字面量的效率更高
郵箱的正則匹配:
varregMail?=/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;
70 Javascript中callee和caller的作用?
caller是返回一個對函數的引用,該函數調用了當前函數;
callee是返回正在被執行的function函數,也就是所指定的function對象的正文
那么問題來了?如果一對兔子每月生一對兔子;一對新生兔,從第二個月起就開始生兔子;假定每對兔子都是一雌一雄,試問一對兔子,第n個月能繁殖成多少對兔子?(使用callee完成)
varresult=[];functionfn(n){//典型的斐波那契數列if(n==1){return1;?????}elseif(n==2){return1;?????}else{if(result[n]){returnresult[n];?????????}else{//argument.callee()表示fn()result[n]=arguments.callee(n-1)+arguments.callee(n-2);returnresult[n];?????????}????}?}
71 window.onload和$(document).ready
原生JS的window.onload與Jquery的$(document).ready(function(){})有什么不同?如何用原生JS實現Jq的ready方法?
window.onload()方法是必須等到頁面內包括圖片的所有元素加載完畢后才能執行。
$(document).ready()是DOM結構繪制完畢后就執行,不必等到加載完畢
functionready(fn){if(document.addEventListener)?{//標準瀏覽器document.addEventListener('DOMContentLoaded',function(){//注銷事件,?避免反復觸發document.removeEventListener('DOMContentLoaded',arguments.callee,false);??????????????fn();//執行函數},false);??????}elseif(document.attachEvent)?{//IEdocument.attachEvent('onreadystatechange',function(){if(document.readyState?=='complete')?{document.detachEvent('onreadystatechange',arguments.callee);?????????????????fn();//函數執行}?????????});?????}?};
72 addEventListener()和attachEvent()的區別
addEventListener()是符合W3C規范的標準方法;attachEvent()是IE低版本的非標準方法
addEventListener()支持事件冒泡和事件捕獲; - 而attachEvent()只支持事件冒泡
addEventListener()的第一個參數中,事件類型不需要添加on;attachEvent()需要添加'on'
如果為同一個元素綁定多個事件,addEventListener()會按照事件綁定的順序依次執行,attachEvent()會按照事件綁定的順序倒序執行
varresultArr=?[];varinput?=document.querySelectorAll('input');for(vari?=0;?i?<?input.length;?i++?)?{if(?input[i].type?=='checkbox')?{????????resultArr.push(?input[i]?);????}}//resultArr即中獲取到了頁面中的所有checkbox