1.eval是做什么的藻雪?為什么盡量避免使用eval万搔?
- Javascript全局對象蘸嘶,eval()函數(shù)可以計(jì)算機(jī)某個(gè)字符串,并計(jì)算其中的JS代碼计雌。
- eval只在被直接調(diào)用且調(diào)用函數(shù)就是eval本身時(shí)才會(huì)在當(dāng)前作用域執(zhí)行悄晃,否則會(huì)在全局作用域中執(zhí)行。
- eval()可以干擾作用域鏈凿滤,eval()可以訪問和修改它外部作用域中的變量妈橄。
- eval也存在安全問題,因?yàn)樗鼤?huì)執(zhí)行任意傳給它的代碼翁脆, 在代碼字符串未知或者是來自一個(gè)不信任的源時(shí)眷蚓,絕對不要使用eval函數(shù)。當(dāng)處理Ajax請求得到的JSON相應(yīng)的時(shí)候反番。在這些情況下沙热,最好使用JavaScript內(nèi)置方法來解析JSON相應(yīng),以確保安全和有效罢缸。若瀏覽器不支持JSON.parse()校读,你可以使用來自JSON.org的庫。
- eval不容易調(diào)試祖能。用chromeDev等調(diào)試工具無法打斷點(diǎn)調(diào)試歉秫。
- 說到性能問題,在舊的瀏覽器中如果你使用了eval养铸,性能會(huì)下降10倍雁芙。在現(xiàn)代瀏覽器中有兩種編譯模式:fast path和slow path轧膘。fast path是編譯那些穩(wěn)定和可預(yù)測(stable and predictable)的代碼。而明顯的兔甘,eval不可預(yù)測谎碍,所以將會(huì)使用slow path,所以會(huì)慢洞焙。(2次蟆淀,一次解析js,一次執(zhí)行澡匪。)
2.null和undefined的區(qū)別熔任?
- undefined類型值只有一個(gè)即undefined, 當(dāng)聲明的變量還未被初始化時(shí),變量的默認(rèn)值為undefined唁情。
- Null類型的值只有一個(gè)即null,null用來表示尚未存在的對象疑苔,常用來表示函數(shù)企圖返回一個(gè)不存在的對象。
alert(typeof undefined); //output "undefined"
alert(typeof null); //output "object"
第一行代碼很容易理解甸鸟,undefined的類型為Undefined惦费;第二行代碼卻讓人疑惑,為什么null的類型又是Object了呢抢韭?其實(shí)這是JavaScript最初實(shí)現(xiàn)的一個(gè)錯(cuò)誤薪贫,后來被ECMAScript沿用下來。在今天我們可以解釋為刻恭,null即是一個(gè)不存在的對象的占位符后雷,但是在實(shí)際編碼時(shí)還是要注意這一特性。
alert(null == undefined); //output "true"
ECMAScript認(rèn)為undefined是從null派生出來的吠各,所以把它們定義為相等的。但是勉抓,如果在一些情況下贾漏,我們一定要區(qū)分這兩個(gè)值,那應(yīng)該怎么辦呢藕筋?可以使用下面的兩種方法纵散。
alert(null === undefined); //output "false"
alert(typeof null == typeof undefined); //output "false"
使用typeof方法在前面已經(jīng)講過,null與undefined的類型是不一樣的隐圾,所以輸出"false"伍掀。而===代表絕對等于,在這里null === undefined輸出false暇藏。
2 寫一個(gè)通用的事件偵聽器函數(shù)蜜笤。
// event(事件)工具集,來源:github.com/markyun
markyun.Event = {
// 頁面加載完成后
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 視能力分別使用dom0||dom2||IE方式 來綁定事件
// 參數(shù): 操作的元素,事件名稱 ,事件處理程序
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件類型盐碱、需要執(zhí)行的函數(shù)把兔、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, function() {
handler.call(element);
});
} else {
element['on' + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
},
// 阻止事件 (主要是事件冒泡沪伙,因?yàn)镮E不支持事件捕獲)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的默認(rèn)行為
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 獲取事件目標(biāo)
getTarget : function(event) {
return event.target || event.srcElement;
},
// 獲取event對象的引用,取到事件的所有信息县好,確保隨時(shí)能使用event围橡;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while (c) {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};
3.模塊化怎么做?
立即執(zhí)行函數(shù)缕贡,不暴露私有成員
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();
4."use strict";是什么意思 ? 使用它的好處和壞處分別是什么翁授?
ECMAscript 5添加了第二種運(yùn)行模式:"嚴(yán)格模式"(strict mode)。顧名思義晾咪,這種模式使得Javascript在更嚴(yán)格的條件下運(yùn)行收擦。
設(shè)立"嚴(yán)格模式"的目的,主要有以下幾個(gè):
1. 消除Javascript語法的一些不合理禀酱、不嚴(yán)謹(jǐn)之處炬守,減少一些怪異行為;
2. 消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全;
3. 提高編譯器效率剂跟,增加運(yùn)行速度;
4. 為未來新版本的Javascript做好鋪墊减途。
注:經(jīng)過測試 IE6,7,8,9 均不支持嚴(yán)格模式。
缺點(diǎn):
現(xiàn)在網(wǎng)站的 JS 都會(huì)進(jìn)行壓縮曹洽,一些文件用了嚴(yán)格模式鳍置,而另一些沒有。這時(shí)這些本來是嚴(yán)格模式的文件送淆,被 merge后税产,這個(gè)串就到了文件的中間,不僅沒有指示嚴(yán)格模式偷崩,反而在壓縮后浪費(fèi)了字節(jié)辟拷。
怎么寫
首先嚴(yán)格模式可以寫在整個(gè)腳本或模塊中,也可以寫在函數(shù)中.如果寫在全局環(huán)境,可以直接在文件的第一句加入"use strict"就可以了. 但是如果這么寫的話你就慘了.
假如你的文件引入其它腳本文件時(shí).假如其它腳本沒有啟用嚴(yán)格模式你將面臨很多問題.所以建議把嚴(yán)格模式寫在函數(shù)中,寫在函數(shù)內(nèi)的第一句就可以了.
作用
去除with關(guān)鍵字,使用嚴(yán)格模式后,with關(guān)鍵字會(huì)報(bào)錯(cuò)不支持
with(){
}
這樣的寫法了.
防止意外的全局變量,這樣不帶var的聲明變量也不可以了.
a = 2;
函數(shù)中未定義或者為null的this不在指向全局變量.防止依賴函數(shù)中的默認(rèn)this行為代碼出錯(cuò).
//"use strict"
this.color = "red";
function sayColor() {
console.log(this.color);
}
sayColor();\\undefined
sayColor.call(null);\\undefined
嚴(yán)格模式
"use strict"
this.color = "red";
function sayColor() {
console.log(this.color);
}
sayColor();
sayColor.call(null);
console.log(this.color);//TypeError: Cannot read property 'color' of undefined
另一種情況
"use strict"
function Person(name) {
this.name = name;
}
var me = Person("Nicholas");
this.name = name;
^
TypeError: Cannot set property 'name' of undefined
原型繼承
"use strict"
function Person(name) {
this.name = name;
}
var me = new Person("Nicholas");
沒有報(bào)錯(cuò). 原來這樣. this = proto = prototype 這些屬性都是在new 一個(gè)新的對象. 就是在原型繼承的時(shí)候賦值的.
重命名變量會(huì)報(bào)錯(cuò),這個(gè)不多說了,都理解.
安全的eval()
``js
//"use strict";
var y = eval("var x=10;");
console.log(x); //10
```js
"use strict";
var y = eval("var x=10;");
console.log(x);
console.log(x);
^
ReferenceError: x is not defined
禁止對只讀屬性賦值
// "use strict";
var person = {};
Object.defineProperty(person, "name",{
writable: false,
value: "Nicholas"
});
person.name = "John";
以上正確
"use strict";
var person = {};
Object.defineProperty(person, "name",{
writable: false,
value: "Nicholas"
});
person.name = "John";
報(bào)錯(cuò):
c:\Users\Feng Huang\WebstormProjects\MemberManagement\test4.js:13
person.name = "John";
^
TypeError: Cannot assign to read only property 'name' of #<Object>
提示只讀屬性不能賦值.
new操作符具體干了什么呢?
1、創(chuàng)建一個(gè)空對象阐斜,并且 this 變量引用該對象衫冻,同時(shí)還繼承了該函數(shù)的原型。
2谒出、屬性和方法被加入到 this 引用的對象中隅俘。
3、新創(chuàng)建的對象由 this 所引用笤喳,并且最后隱式的返回 this 为居。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
Javascript中,有一個(gè)函數(shù)杀狡,執(zhí)行時(shí)對象查找時(shí)蒙畴,永遠(yuǎn)不會(huì)去查找原型,這個(gè)函數(shù)是呜象?
hasOwnProperty()
["1", "2", "3"].map(parseInt) 答案是多少忍抽?
[1, NaN, NaN] 因?yàn)?parseInt 需要兩個(gè)參數(shù) (val, radix)八孝,其中 radix 表示解析時(shí)用的基數(shù)。map 傳了 3 個(gè) (element, index, array)鸠项,對應(yīng)的 radix 不合法導(dǎo)致解析失敗干跛。
談?wù)凾his對象的理解。
this是js的一個(gè)關(guān)鍵字祟绊,隨著函數(shù)使用場合不同楼入,this的值會(huì)發(fā)生變化。 但是有一個(gè)總原則牧抽,那就是this指的是調(diào)用函數(shù)的那個(gè)對象嘉熊。 this一般情況下:是全局對象Global。 作為方法調(diào)用扬舒,那么this就是指這個(gè)對象.
js延遲加載的方式有哪些阐肤?
defer和async、動(dòng)態(tài)創(chuàng)建DOM方式(用得最多)讲坎、按需異步載入js.
defer
定義和用法
defer 屬性規(guī)定是否對腳本執(zhí)行進(jìn)行延遲孕惜,直到頁面加載為止。
有的 javascript 腳本 document.write 方法來創(chuàng)建當(dāng)前的文檔內(nèi)容晨炕,其他腳本就不一定是了衫画。
如果您的腳本不會(huì)改變文檔的內(nèi)容,可將 defer 屬性加入到 <script> 標(biāo)簽中瓮栗,以便加快處理文檔的速度削罩。因?yàn)闉g覽器知道它將能夠安全地讀取文檔的剩余部分而不用執(zhí)行腳本,它將推遲對腳本的解釋费奸,直到文檔已經(jīng)顯示給用戶為止弥激。
瀏覽器支持
只有 Internet Explorer (9以前)支持 defer 屬性。
async
定義和用法
async 屬性規(guī)定一旦腳本可用愿阐,則會(huì)異步執(zhí)行微服。
注釋:async 屬性僅適用于外部腳本(只有在使用 src 屬性時(shí))。
注釋:有多種執(zhí)行外部腳本的方法:
- 如果 async="async":腳本相對于頁面的其余部分異步地執(zhí)行(當(dāng)頁面繼續(xù)進(jìn)行解析時(shí)换况,腳本將被執(zhí)行)
- 如果不使用 async 且 defer="defer":腳本將在頁面完成解析時(shí)執(zhí)行
- 如果既不使用 async 也不使用 defer:在瀏覽器繼續(xù)解析頁面之前,立即讀取并執(zhí)行腳本
語法
<script async="async">
HTML 4.01 與 HTML 5 之間的差異
async 屬性是 HTML5 中的新屬性
async和defer 的區(qū)別
defer 屬性標(biāo)注的腳本是延遲腳本盗蟆,使得瀏覽器延遲腳本的執(zhí)行戈二,也就是說,腳本會(huì)被異步下載但是不會(huì)被執(zhí)行喳资,直到文檔的載入和解析完成觉吭,并可以操作,腳本才會(huì)被執(zhí)行仆邓。
async 屬性標(biāo)注的腳本是異步腳本鲜滩,即異步下載腳本時(shí)伴鳖,不會(huì)阻塞文檔解析,但是一旦下載完成后徙硅,立即執(zhí)行榜聂,阻塞文檔解析。
延遲腳本會(huì)按他們在文檔里的出現(xiàn)順序執(zhí)行
異步腳本在它們載入后執(zhí)行嗓蘑,但是不能保證執(zhí)行順序须肆。
使用async的意義就在于使得下載腳本時(shí),不會(huì)阻塞文檔的解析桩皿。因?yàn)閍sync的腳本執(zhí)行順序是沒有保證的豌汇,因此要確認(rèn)腳本間沒有依賴關(guān)系。
現(xiàn)在呢基本上都是在文檔的最后寫腳本泄隔,那么這和 defer 的區(qū)別在哪里呢?
第一點(diǎn)當(dāng)然是異步下載腳本了拒贱,第二點(diǎn)就是 使用async或defer任何一個(gè)都意味著在腳本里不能出現(xiàn) document.write。