面经之js

1.eval是做什么的?为什么尽量避免使用eval?

  1. 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的区别?

  1. undefined类型值只有一个即undefined, 当声明的变量还未被初始化时,变量的默认值为undefined。
  2. 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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 第一章: JS简介 从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数, 甚至元编程等...
    LaBaby_阅读 1,656评论 0 6
  • 有人说过,很多弯路到最后都成了直路,所有的坑到最后也都成了坦途;所谓的直路和坦途并不是摆在眼前的,都是不断的的...
    老衲法号一眉道人阅读 1,321评论 0 4
  • 在线阅读 http://interview.poetries.top[http://interview.poetr...
    程序员poetry阅读 114,315评论 24 450
  • 天还没亮,一个人开着车驰骋在熟悉的路上,仗着大清早路上没几辆车,油门不自觉踩的比平常要深一些。乡下公路没有路灯,司...
    李诗民阅读 1,264评论 7 4
  • 最近总有人提起思维导图 让我想起我最早接触思维导图的夏令营 可惜没什么照片可作纪念 很想要当时画的第一张思维导图(...
    UKA的嗯阅读 283评论 0 0