1.eval是做什么的?为什么尽量避免使用eval?
- Javascript全局对象,eval()函数可以计算机某个字符串,并计算其中的JS代码。
- eval只在被直接调用且调用函数就是eval本身时才会在当前作用域执行,否则会在全局作用域中执行。
- eval()可以干扰作用域链,eval()可以访问和修改它外部作用域中的变量。
- eval也存在安全问题,因为它会执行任意传给它的代码, 在代码字符串未知或者是来自一个不信任的源时,绝对不要使用eval函数。当处理Ajax请求得到的JSON相应的时候。在这些情况下,最好使用JavaScript内置方法来解析JSON相应,以确保安全和有效。若浏览器不支持JSON.parse(),你可以使用来自JSON.org的库。
- eval不容易调试。用chromeDev等调试工具无法打断点调试。
- 说到性能问题,在旧的浏览器中如果你使用了eval,性能会下降10倍。在现代浏览器中有两种编译模式:fast path和slow path。fast path是编译那些稳定和可预测(stable and predictable)的代码。而明显的,eval不可预测,所以将会使用slow path,所以会慢。(2次,一次解析js,一次执行。)
2.null和undefined的区别?
- undefined类型值只有一个即undefined, 当声明的变量还未被初始化时,变量的默认值为undefined。
- Null类型的值只有一个即null,null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象。
alert(typeof undefined); //output "undefined"
alert(typeof null); //output "object"
第一行代码很容易理解,undefined的类型为Undefined;第二行代码却让人疑惑,为什么null的类型又是Object了呢?其实这是JavaScript最初实现的一个错误,后来被ECMAScript沿用下来。在今天我们可以解释为,null即是一个不存在的对象的占位符,但是在实际编码时还是要注意这一特性。
alert(null == undefined); //output "true"
ECMAScript认为undefined是从null派生出来的,所以把它们定义为相等的。但是,如果在一些情况下,我们一定要区分这两个值,那应该怎么办呢?可以使用下面的两种方法。
alert(null === undefined); //output "false"
alert(typeof null == typeof undefined); //output "false"
使用typeof方法在前面已经讲过,null与undefined的类型是不一样的,所以输出"false"。而===代表绝对等于,在这里null === undefined输出false。
2 写一个通用的事件侦听器函数。
// 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方式 来绑定事件
// 参数: 操作的元素,事件名称 ,事件处理程序
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件类型、需要执行的函数、是否捕捉
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;
}
},
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的默认行为
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 获取事件目标
getTarget : function(event) {
return event.target || event.srcElement;
},
// 获取event对象的引用,取到事件的所有信息,确保随时能使用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.模块化怎么做?
立即执行函数,不暴露私有成员
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();
4."use strict";是什么意思 ? 使用它的好处和坏处分别是什么?
ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。
设立"严格模式"的目的,主要有以下几个:
1. 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
2. 消除代码运行的一些不安全之处,保证代码运行的安全;
3. 提高编译器效率,增加运行速度;
4. 为未来新版本的Javascript做好铺垫。
注:经过测试 IE6,7,8,9 均不支持严格模式。
缺点:
现在网站的 JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。
怎么写
首先严格模式可以写在整个脚本或模块中,也可以写在函数中.如果写在全局环境,可以直接在文件的第一句加入"use strict"就可以了. 但是如果这么写的话你就惨了.
假如你的文件引入其它脚本文件时.假如其它脚本没有启用严格模式你将面临很多问题.所以建议把严格模式写在函数中,写在函数内的第一句就可以了.
作用
去除with关键字,使用严格模式后,with关键字会报错不支持
with(){
}
这样的写法了.
防止意外的全局变量,这样不带var的声明变量也不可以了.
a = 2;
函数中未定义或者为null的this不在指向全局变量.防止依赖函数中的默认this行为代码出错.
//"use strict"
this.color = "red";
function sayColor() {
console.log(this.color);
}
sayColor();\\undefined
sayColor.call(null);\\undefined
严格模式
"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");
没有报错. 原来这样. this = proto = prototype 这些属性都是在new 一个新的对象. 就是在原型继承的时候赋值的.
重命名变量会报错,这个不多说了,都理解.
安全的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";
报错:
c:\Users\Feng Huang\WebstormProjects\MemberManagement\test4.js:13
person.name = "John";
^
TypeError: Cannot assign to read only property 'name' of #<Object>
提示只读属性不能赋值.
new操作符具体干了什么呢?
1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
hasOwnProperty()
["1", "2", "3"].map(parseInt) 答案是多少?
[1, NaN, NaN] 因为 parseInt 需要两个参数 (val, radix),其中 radix 表示解析时用的基数。map 传了 3 个 (element, index, array),对应的 radix 不合法导致解析失败。
谈谈This对象的理解。
this是js的一个关键字,随着函数使用场合不同,this的值会发生变化。 但是有一个总原则,那就是this指的是调用函数的那个对象。 this一般情况下:是全局对象Global。 作为方法调用,那么this就是指这个对象.
js延迟加载的方式有哪些?
defer和async、动态创建DOM方式(用得最多)、按需异步载入js.
defer
定义和用法
defer 属性规定是否对脚本执行进行延迟,直到页面加载为止。
有的 javascript 脚本 document.write 方法来创建当前的文档内容,其他脚本就不一定是了。
如果您的脚本不会改变文档的内容,可将 defer 属性加入到 <script> 标签中,以便加快处理文档的速度。因为浏览器知道它将能够安全地读取文档的剩余部分而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。
浏览器支持
只有 Internet Explorer (9以前)支持 defer 属性。
async
定义和用法
async 属性规定一旦脚本可用,则会异步执行。
注释:async 属性仅适用于外部脚本(只有在使用 src 属性时)。
注释:有多种执行外部脚本的方法:
- 如果 async="async":脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)
- 如果不使用 async 且 defer="defer":脚本将在页面完成解析时执行
- 如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本
语法
<script async="async">
HTML 4.01 与 HTML 5 之间的差异
async 属性是 HTML5 中的新属性
async和defer 的区别
defer 属性标注的脚本是延迟脚本,使得浏览器延迟脚本的执行,也就是说,脚本会被异步下载但是不会被执行,直到文档的载入和解析完成,并可以操作,脚本才会被执行。
async 属性标注的脚本是异步脚本,即异步下载脚本时,不会阻塞文档解析,但是一旦下载完成后,立即执行,阻塞文档解析。
延迟脚本会按他们在文档里的出现顺序执行
异步脚本在它们载入后执行,但是不能保证执行顺序。
使用async的意义就在于使得下载脚本时,不会阻塞文档的解析。因为async的脚本执行顺序是没有保证的,因此要确认脚本间没有依赖关系。
现在呢基本上都是在文档的最后写脚本,那么这和 defer 的区别在哪里呢?
第一点当然是异步下载脚本了,第二点就是 使用async或defer任何一个都意味着在脚本里不能出现 document.write。