面试题1

GitHub - Tonyhzw/FE-interview: 收集的前端面试题和答案
Skip to content
Ignore Learn more
Please note that GitHub no longer supports old versions of Internet Explorer.

We recommend upgrading to the latest Microsoft Edge, Google Chrome, or Firefox.

If you are using IE 11, make sure you turn off “Compatibility View”.

      







Business

Explore

Pricing

  



This repository

#veinticuatro, x:-moz-any-link { color: red } /* Firefox 3.0+ */ #veinticinco, x:-moz-any-link, x:default { color: red }
  • 属性hack:不同浏览器解析bug或方法
/* IE6 */




#once { _color: blue } /* IE6, IE7 */ #doce { *color: blue; /* or #color: blue */ } /* Everything but IE6 */ #diecisiete { color/**/: blue } /* IE6, IE7, IE8 */ #diecinueve { color: blue\9; } /* IE7, IE8 */ #veinte { color/*\**/: blue\9; } /* IE6, IE7 -- acts as an !important */ #veintesiete { color: blue !ie; } /* string after ! can be anything */

specified value,computed value,used value计算方法

  • specified value: 计算方法如下:

    1. 如果样式表设置了一个值,使用这个值
    2. 如果没有设置值,这个属性是继承属性,从父元素继承
    3. 如果没设置,并且不是继承属性,使用css规范指定的初始值
  • computed value: 以specified value根据规范定义的行为进行计算,通常将相对值计算为绝对值,例如em根据font-size进行计算。一些使用百分数并且需要布局来决定最终值的属性,如width,margin。百分数就直接作为computed value。line-height的无单位值也直接作为computed value。这些值将在计算used value时得到绝对值。computed value的主要作用是用于继承

  • used value:属性计算后的最终值,对于大多数属性可以通过window.getComputedStyle获得,尺寸值单位为像素。以下属性依赖于布局,

    • background-position
    • bottom, left, right, top
    • height, width
    • margin-bottom, margin-left, margin-right, margin-top
    • min-height, min-width
    • padding-bottom, padding-left, padding-right, padding-top
    • text-indent

link@import的区别

  1. link是HTML方式, @import是CSS方式
  2. link最大限度支持并行下载,@import过多嵌套导致串行下载,出现FOUC
  3. link可以通过rel="alternate stylesheet"指定候选样式
  4. 浏览器对link支持早于@import,可以使用@import对老浏览器隐藏样式
  5. @import必须在样式规则之前,可以在css文件中引用其他文件
  6. 总体来说:link优于@import

display: block;display: inline;的区别

block元素特点:

1.处于常规流中时,如果width没有设置,会自动填充满父容器 2.可以应用margin/padding 3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略vertical-align

inline元素特点

1.水平方向上根据direction依次布局 2.不会在元素前后进行换行 3.受white-space控制 4.margin/padding在竖直方向上无效,水平方向上有效 5.width/height属性对非替换行内元素无效,宽度由元素内容决定 6.非替换行内元素的行框高由line-height确定,替换行内元素的行框高由height,margin,padding,border决定 6.浮动或绝对定位时会转换为block 7.vertical-align属性生效

PNG,GIF,JPG的区别及如何选

参考资料: 选择正确的图片格式 GIF:

  1. 8位像素,256色
  2. 无损压缩
  3. 支持简单动画
  4. 支持boolean透明
  5. 适合简单动画

JPEG

  1. 颜色限于256
  2. 有损压缩
  3. 可控制压缩质量
  4. 不支持透明
  5. 适合照片

PNG

  1. 有PNG8和truecolor PNG
  2. PNG8类似GIF颜色上限为256,文件小,支持alpha透明度,无动画
  3. 适合图标、背景、按钮

CSS有哪些继承属性

  • 关于文字排版的属性如:
    • font
    • word-break
    • letter-spacing
    • text-align
    • text-rendering
    • word-spacing
    • white-space
    • text-indent
    • text-transform
    • text-shadow
  • line-height
  • color
  • visibility
  • cursor

IE6浏览器有哪些常见的bug,缺陷或者与标准不一致的地方,如何解决

  • IE6不支持min-height,解决办法使用css hack:
.target {
    min-height: 100px;
    height: auto !important;
    height: 100px;   // IE6下内容高度超过会自动扩展高度
}
  • olli的序号全为1,不递增。解决方法:为li设置样式display: list-item;

  • 未定位父元素overflow: auto;,包含position: relative;子元素,子元素高于父元素时会溢出。解决办法:1)子元素去掉position: relative;; 2)不能为子元素去掉定位时,父元素position: relative;



  • IE6只支持a标签的:hover伪类,解决方法:使用js为元素监听mouseenter,mouseleave事件,添加类实现效果:


aaaa bbbbbDDDDDDDDDDDd aaaa lkjlkjdf j

  • IE5-8不支持opacity,解决办法:http://blog.csdn.net/freshlover/article/details/17143341
.opacity {
    opacity: 0.6
    filter: alpha(opacity=60); /* for IE5-7 */
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; /* for IE 8*/
}
  • IE6在设置height小于font-size时高度值为font-size,解决办法:font-size: 0;
  • IE6不支持PNG透明背景,解决办法: IE6下使用gif图片
  • IE6-7不支持display: inline-block解决办法:设置inline并触发hasLayout
    display: inline-block;
    *display: inline;
    *zoom: 1;
  • IE6下浮动元素在浮动方向上与父元素边界接触元素的外边距会加倍。解决办法: 1)使用padding控制间距。 2)浮动元素display: inline;这样解决问题且无任何副作用:css标准规定浮动元素display:inline会自动调整为block
  • 通过为块级元素设置宽度和左右margin为auto时,IE6不能实现水平居中,解决方法:为父元素设置text-align: center;

容器包含若干浮动元素时如何清理(包含)浮动

  1. 容器元素闭合标签前添加额外元素并设置clear: both
  2. 父元素触发块级格式化上下文(见块级可视化上下文部分)
  3. 设置容器元素伪元素进行清理推荐的清理浮动方法
/**
* 在标准浏览器下使用
* 1 content内容为空格用于修复opera下文档中出现
*   contenteditable属性时在清理浮动元素上下的空白
* 2 使用display使用table而不是block:可以防止容器和
*   子元素top-margin折叠,这样能使清理效果与BFC,IE6/7
*   zoom: 1;一致
**/

.clearfix:before,
.clearfix:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.clearfix:after {
    clear: both;
}

/**
* IE 6/7下使用
* 通过触发hasLayout实现包含浮动
**/
.clearfix {
    *zoom: 1;
}

什么是FOUC?如何避免

Flash Of Unstyled Content:用户定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再从新显示文档,造成页面闪烁。解决方法:把样式表放到文档的head

如何创建块级格式化上下文(block formatting context),BFC有什么用

创建规则:

  1. 根元素
  2. 浮动元素(float不是none
  3. 绝对定位元素(position取值为absolutefixed
  4. display取值为inline-block,table-cell, table-caption,flex, inline-flex之一的元素
  5. overflow不是visible的元素

作用:

  1. 可以包含浮动元素
  2. 不被浮动元素覆盖
  3. 阻止父子元素的margin折叠

display,float,position的关系

  1. 如果display为none,那么position和float都不起作用,这种情况下元素不产生框
  2. 否则,如果position值为absolute或者fixed,框就是绝对定位的,float的计算值为none,display根据下面的表格进行调整。
  3. 否则,如果float不是none,框是浮动的,display根据下表进行调整
  4. 否则,如果元素是根元素,display根据下表进行调整
  5. 其他情况下display的值为指定值 总结起来:绝对定位、浮动、根元素都需要调整display

外边距折叠(collapsing margins)

毗邻的两个或多个margin会合并成一个margin,叫做外边距折叠。规则如下:

  1. 两个或多个毗邻的普通流中的块元素垂直方向上的margin会折叠
  2. 浮动元素/inline-block元素/绝对定位元素的margin不会和垂直方向上的其他元素的margin折叠
  3. 创建了块级格式化上下文的元素,不会和它的子元素发生margin折叠
  4. 元素自身的margin-bottom和margin-top相邻时也会折叠

如何确定一个元素的包含块(containing block)

  1. 根元素的包含块叫做初始包含块,在连续媒体中他的尺寸与viewport相同并且anchored at the canvas origin;对于paged media,它的尺寸等于page area。初始包含块的direction属性与根元素相同。

  2. positionrelative或者static的元素,它的包含块由最近的块级(displayblock,list-item, table)祖先元素的内容框组成

  3. 如果元素positionfixed。对于连续媒体,它的包含块为viewport;对于paged media,包含块为page area

  4. 如果元素positionabsolute,它的包含块由祖先元素中最近一个positionrelative,absolute或者fixed的元素产生,规则如下:

    • 如果祖先元素为行内元素,the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element.
    • 其他情况下包含块由祖先节点的padding edge组成

    如果找不到定位的祖先元素,包含块为初始包含块

stacking context,布局规则

z轴上的默认层叠顺序如下(从下到上):

  1. 根元素的边界和背景
  2. 常规流中的元素按照html中顺序
  3. 浮动块
  4. positioned元素按照html中出现顺序

如何创建stacking context:

  1. 根元素
  2. z-index不为auto的定位元素
  3. a flex item with a z-index value other than ‘auto’
  4. opacity小于1的元素
  5. 在移动端webkit和chrome22+,z-index为auto,position: fixed也将创建新的stacking context

如何水平居中一个元素

  • 如果需要居中的元素为常规流中inline元素,为父元素设置text-align: center;即可实现
  • 如果需要居中的元素为常规流中block元素,1)为元素设置宽度,2)设置左右margin为auto。3)IE6下需在父元素上设置text-align: center;,再给子元素恢复需要的值

    
aaaaaa aaaaaa a a a a a a a a
  • 如果需要居中的元素为浮动元素,1)为元素设置宽度,2)position: relative;,3)浮动方向偏移量(left或者right)设置为50%,4)浮动方向上的margin设置为元素宽度一半乘以-1

    
aaaaaa aaaaaa a a a a a a a a
  • 如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)偏移量设置为50%,3)偏移方向外边距设置为元素宽度一半乘以-1

    
aaaaaa aaaaaa a a a a a a a a
  • 如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)设置左右偏移量都为0,3)设置左右外边距都为auto

    
aaaaaa aaaaaa a a a a a a a a

如何竖直居中一个元素

参考资料:6 Methods For Vertical Centering With CSS。 盘点8种CSS实现垂直居中

  • 需要居中元素为单行文本,为包含文本的元素设置大于font-sizeline-height

center text

$javascript概念部分

DOM元素e的e.getAttribute(propName)和e.propName有什么区别和联系

offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别

  • offsetWidth/offsetHeight返回值包含content + padding + border,效果与e.getBoundingClientRect()相同
  • clientWidth/clientHeight返回值只包含content + padding,如果有滚动条,也不包含滚动条
  • scrollWidth/scrollHeight返回值包含content + padding + 溢出内容的尺寸

Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9

XMLHttpRequest通用属性和方法

  1. readyState:表示请求状态的整数,取值:
  • UNSENT(0):对象已创建
  • OPENED(1):open()成功调用,在这个状态下,可以为xhr设置请求头,或者使用send()发送请求
  • HEADERS_RECEIVED(2):所有重定向已经自动完成访问,并且最终响应的HTTP头已经收到
  • LOADING(3):响应体正在接收
  • DONE(4):数据传输完成或者传输产生错误
  1. onreadystatechange:readyState改变时调用的函数
  2. status:服务器返回的HTTP状态码(如,200, 404)
  3. statusText:服务器返回的HTTP状态信息(如,OK,No Content)
  4. responseText:作为字符串形式的来自服务器的完整响应
  5. responseXML: Document对象,表示服务器的响应解析成的XML文档
  6. abort():取消异步HTTP请求
  7. getAllResponseHeaders(): 返回一个字符串,包含响应中服务器发送的全部HTTP报头。每个报头都是一个用冒号分隔开的名/值对,并且使用一个回车/换行来分隔报头行
  8. getResponseHeader(headerName):返回headName对应的报头值
  9. open(method, url, asynchronous [, user, password]):初始化准备发送到服务器上的请求。method是HTTP方法,不区分大小写;url是请求发送的相对或绝对URL;asynchronous表示请求是否异步;user和password提供身份验证
  10. setRequestHeader(name, value):设置HTTP报头
  11. send(body):对服务器请求进行初始化。参数body包含请求的主体部分,对于POST请求为键值对字符串;对于GET请求,为null

focus/blur与focusin/focusout的区别与联系

  1. focus/blur不冒泡,focusin/focusout冒泡
  2. focus/blur兼容性好,focusin/focusout在除FireFox外的浏览器下都保持良好兼容性,如需使用事件托管,可考虑在FireFox下使用事件捕获elem.addEventListener(‘focus’, handler, true)
  3. 可获得焦点的元素:
    1. window
    2. 链接被点击或键盘操作
    3. 表单空间被点击或键盘操作
    4. 设置tabindex属性的元素被点击或键盘操作

mouseover/mouseout与mouseenter/mouseleave的区别与联系

  1. mouseover/mouseout是标准事件,所有浏览器都支持;mouseenter/mouseleave是IE5.5引入的特有事件后来被DOM3标准采纳,现代标准浏览器也支持
  2. mouseover/mouseout是冒泡事件;mouseenter/mouseleave不冒泡。需要为多个元素监听鼠标移入/出事件时,推荐mouseover/mouseout托管,提高性能
  3. 标准事件模型中event.target表示发生移入/出的元素,vent.relatedTarget对应移出/如元素;在老IE中event.srcElement表示发生移入/出的元素,event.toElement表示移出的目标元素,event.fromElement表示移入时的来源元素

例子:鼠标从div#target元素移出时进行处理,判断逻辑如下:

test

sessionStorage,localStorage,cookie区别

  1. 都会在浏览器端保存,有大小限制,同源限制
  2. cookie会在请求时发送到服务器,作为会话标识,服务器可修改cookie;web storage不会发送到服务器
  3. cookie有path概念,子路径可以访问父路径cookie,父路径不能访问子路径cookie
  4. 有效期:cookie在设置的有效期内有效,默认为浏览器关闭;sessionStorage在窗口关闭前有效,localStorage长期有效,直到用户删除
  5. 共享:sessionStorage不能共享,localStorage在同源文档之间共享,cookie在同源且符合path规则的文档之间共享
  6. localStorage的修改会促发其他文档窗口的update事件
  7. cookie有secure属性要求HTTPS传输
  8. 浏览器不能保存超过300个cookie,单个服务器不能超过20个,每个cookie不能超过4k。web storage大小支持能达到5M

javascript跨域通信

同源:两个文档同源需满足

  1. 协议相同
  2. 域名相同
  3. 端口相同

跨域通信:js进行DOM操作、通信时如果目标与当前窗口不满足同源条件,浏览器为了安全会阻止跨域操作。跨域通信通常有以下方法

  • 如果是log之类的简单单项通信,新建,

    请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是”今天是星期一”

    var days = ['日','一','二','三','四','五','六'];
    var date = new Date();
    
    console.log('今天是星期' + days[date.getDay()]);
    

    下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果

    for (var i = 0; i < 5; ++i) {
      setTimeout(function () {
        console.log(i + ' ');
      }, 100);
    }
    

    不能输出正确结果,因为循环中setTimeout接受的参数函数通过闭包访问变量i。javascript运行环境为单线程,setTimeout注册的函数需要等待线程空闲才能执行,此时for循环已经结束,i值为5.五个定时输出都是5 修改方法:将setTimeout放在函数立即调用表达式中,将i值作为参数传递给包裹函数,创建新闭包

    for (var i = 0; i < 5; ++i) {
      (function (i) {
        setTimeout(function () {
          console.log(i + ' ');
        }, 100);
      }(i));
    }
    

    现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法

    function Page() {}
    
    Page.prototype = {
      constructor: Page,
    
      postA: function (a) {
        console.log('a:' + a);
      },
      postB: function (b) {
        console.log('b:' + b);
      },
      postC: function (c) {
        console.log('c:' + c);
      },
      check: function () {
        return Math.random() > 0.5;
      }
    }
    
    function checkfy(obj) {
      for (var key in obj) {
        if (key.indexOf('post') === 0 && typeof obj[key] === 'function') {
          (function (key) {
            var fn = obj[key];
            obj[key] = function () {
              if (obj.check()) {
                fn.apply(obj, arguments);
              }
            };
          }(key));
        }
      }
    } // end checkfy()
    
    checkfy(Page.prototype);
    
    var obj = new Page();
    
    obj.postA('checkfy');
    obj.postB('checkfy');
    obj.postC('checkfy');
    

    完成下面的tool-tip

    编写javascript深度克隆函数deepClone

    function deepClone(obj) {
        var _toString = Object.prototype.toString;
    
        // null, undefined, non-object, function
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
    
        // DOM Node
        if (obj.nodeType && 'cloneNode' in obj) {
            return obj.cloneNode(true);
        }
    
        // Date
        if (_toString.call(obj) === '[object Date]') {
            return new Date(obj.getTime());
        }
    
        // RegExp
        if (_toString.call(obj) === '[object RegExp]') {
            var flags = [];
            if (obj.global) { flags.push('g'); }
            if (obj.multiline) { flags.push('m'); }
            if (obj.ignoreCase) { flags.push('i'); }
    
            return new RegExp(obj.source, flags.join(''));
        }
    
        var result = Array.isArray(obj) ? [] :
            obj.constructor ? new obj.constructor() : {};
    
        for (var key in obj ) {
            result[key] = deepClone(obj[key]);
        }
    
        return result;
    }
    
    function A() {
        this.a = a;
    }
    
    var a = {
        name: 'qiu',
        birth: new Date(),
        pattern: /qiu/gim,
        container: document.body,
        hobbys: ['book', new Date(), /aaa/gim, 111]
    };
    
    var c = new A();
    var b = deepClone(c);
    console.log(c.a === b.a);
    console.log(c, b);
    

    补充代码,鼠标单击Button1后将Button1移动到Button2的后面

    
    
    
        
        TEst
    
    
    
    

    网页中实现一个计算当年还剩多少时间的倒数计时程序,要求网页上实时动态显示”××年还剩××天××时××分××秒”

    
    
    
        
        TEst
    
    
    
        
    
    
    
    
    
    
    

    完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组

    如:[1, [2, [ [3, 4], 5], 6]] => [1, 2, 3, 4, 5, 6]

        var data =  [1, [2, [ [3, 4], 5], 6]];
    
        function flat(data, result) {
            var i, d, len;
            for (i = 0, len = data.length; i < len; ++i) {
                d = data[i];
                if (typeof d === 'number') {
                    result.push(d);
                } else {
                    flat(d, result);
                }
            }
        }
    
        var result = [];
        flat(data, result);
    
        console.log(result);
    

    如何判断一个对象是否为数组

    如果浏览器支持Array.isArray()可以直接判断否则需进行必要判断

    /**
     * 判断一个对象是否是数组,参数不是对象或者不是数组,返回false
     *
     * @param {Object} arg 需要测试是否为数组的对象
     * @return {Boolean} 传入参数是数组返回true,否则返回false
     */
    function isArray(arg) {
        if (typeof arg === 'object') {
            return Object.prototype.toString.call(arg) === '[object Array]';
        }
        return false;
    }
    

    请评价以下事件监听器代码并给出改进意见

    if (window.addEventListener) {
      var addListener = function (el, type, listener, useCapture) {
        el.addEventListener(type, listener, useCapture);
      };
    }
    else if (document.all) {
      addListener = function (el, type, listener) {
        el.attachEvent('on' + type, function () {
          listener.apply(el);
        });
      };
    }
    

    作用:浏览器功能检测实现跨浏览器DOM事件绑定

    优点:

    1. 测试代码只运行一次,根据浏览器确定绑定方法
    2. 通过listener.apply(el)解决IE下监听器this与标准不一致的地方
    3. 在浏览器不支持的情况下提供简单的功能,在标准浏览器中提供捕获功能

    缺点:

    1. document.all作为IE检测不可靠,应该使用if(el.attachEvent)
    2. addListener在不同浏览器下API不一样
    3. listener.apply使this与标准一致但监听器无法移除
    4. 未解决IE下listener参数event。 target问题

    改进:

    var addListener;
    
    if (window.addEventListener) {
      addListener = function (el, type, listener, useCapture) {
        el.addEventListener(type, listener, useCapture);
        return listener;
      };
    }
    else if (window.attachEvent) {
      addListener = function (el, type, listener) {
        // 标准化this,event,target
        var wrapper = function () {
          var event = window.event;
          event.target = event.srcElement;
          listener.call(el, event);
        };
    
        el.attachEvent('on' + type, wrapper);
        return wrapper;
        // 返回wrapper。调用者可以保存,以后remove
      };
    }
    

    如何判断一个对象是否为函数

    /**
     * 判断对象是否为函数,如果当前运行环境对可调用对象(如正则表达式)
     * 的typeof返回'function',采用通用方法,否则采用优化方法
     *
     * @param {Any} arg 需要检测是否为函数的对象
     * @return {boolean} 如果参数是函数,返回true,否则false
     */
    function isFunction(arg) {
        if (arg) {
            if (typeof (/./) !== 'function') {
                return typeof arg === 'function';
            } else {
                return Object.prototype.toString.call(arg) === '[object Function]';
            }
        } // end if
        return false;
    }
    

    编写一个函数接受url中query string为参数,返回解析后的Object,query string使用application/x-www-form-urlencoded编码

    /**
     * 解析query string转换为对象,一个key有多个值时生成数组
     *
     * @param {String} query 需要解析的query字符串,开头可以是?,
     * 按照application/x-www-form-urlencoded编码
     * @return {Object} 参数解析后的对象
     */
    function parseQuery(query) {
        var result = {};
    
        // 如果不是字符串返回空对象
        if (typeof query !== 'string') {
            return result;
        }
    
        // 去掉字符串开头可能带的?
        if (query.charAt(0) === '?') {
            query = query.substring(1);
        }
    
        var pairs = query.split('&');
        var pair;
        var key, value;
        var i, len;
    
        for (i = 0, len = pairs.length; i < len; ++i) {
            pair = pairs[i].split('=');
            // application/x-www-form-urlencoded编码会将' '转换为+
            key = decodeURIComponent(pair[0]).replace(/\+/g, ' ');
            value = decodeURIComponent(pair[1]).replace(/\+/g, ' ');
    
            // 如果是新key,直接添加
            if (!(key in result)) {
                result[key] = value;
            }
            // 如果key已经出现一次以上,直接向数组添加value
            else if (isArray(result[key])) {
                result[key].push(value);
            }
            // key第二次出现,将结果改为数组
            else {
                var arr = [result[key]];
                arr.push(value);
                result[key] = arr;
            } // end if-else
        } // end for
    
        return result;
    }
    
    function isArray(arg) {
        if (arg && typeof arg === 'object') {
            return Object.prototype.toString.call(arg) === '[object Array]';
        }
        return false;
    }
    /**
    console.log(parseQuery('sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8'));
     */
    

    解析一个完整的url,返回Object包含域与window.location相同

    /**
     * 解析一个url并生成window.location对象中包含的域
     * location:
     * {
     *      href: '包含完整的url',
     *      origin: '包含协议到pathname之前的内容',
     *      protocol: 'url使用的协议,包含末尾的:',
     *      username: '用户名', // 暂时不支持
     *      password: '密码',  // 暂时不支持
     *      host: '完整主机名,包含:和端口',
     *      hostname: '主机名,不包含端口'
     *      port: '端口号',
     *      pathname: '服务器上访问资源的路径/开头',
     *      search: 'query string,?开头',
     *      hash: '#开头的fragment identifier'
     * }
     *
     * @param {string} url 需要解析的url
     * @return {Object} 包含url信息的对象
     */
    function parseUrl(url) {
        var result = {};
        var keys = ['href', 'origin', 'protocol', 'host',
                    'hostname', 'port', 'pathname', 'search', 'hash'];
        var i, len;
        var regexp = /(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?/;
    
        var match = regexp.exec(url);
    
        if (match) {
            for (i = keys.length - 1; i >= 0; --i) {
                result[keys[i]] = match[i] ? match[i] : '';
            }
        }
    
        return result;
    }
    

    完成函数getViewportSize返回指定窗口的视口尺寸

    /**
    * 查询指定窗口的视口尺寸,如果不指定窗口,查询当前窗口尺寸
    **/
    function getViewportSize(w) {
        w = w || window;
    
        // IE9及标准浏览器中可使用此标准方法
        if ('innerHeight' in w) {
            return {
                width: w.innerWidth,
                height: w.innerHeight
            };
        }
    
        var d = w.document;
        // IE 8及以下浏览器在标准模式下
        if (document.compatMode === 'CSS1Compat') {
            return {
                width: d.documentElement.clientWidth,
                height: d.documentElement.clientHeight
            };
        }
    
        // IE8及以下浏览器在怪癖模式下
        return {
            width: d.body.clientWidth,
            height: d.body.clientHeight
        };
    }
    

    完成函数getScrollOffset返回窗口滚动条偏移量

    /**
     * 获取指定window中滚动条的偏移量,如未指定则获取当前window
     * 滚动条偏移量
     *
     * @param {window} w 需要获取滚动条偏移量的窗口
     * @return {Object} obj.x为水平滚动条偏移量,obj.y为竖直滚动条偏移量
     */
    function getScrollOffset(w) {
        w =  w || window;
        // 如果是标准浏览器
        if (w.pageXOffset != null) {
            return {
                x: w.pageXOffset,
                y: w.pageYOffset
            };
        }
    
        // 老版本IE,根据兼容性不同访问不同元素
        var d = w.document;
        if (d.compatMode === 'CSS1Compat') {
            return {
                x: d.documentElement.scrollLeft,
                y: d.documentElement.scrollTop
            }
        }
    
        return {
            x: d.body.scrollLeft,
            y: d.body.scrollTop
        };
    }
    

    现有一个字符串richText,是一段富文本,需要显示在页面上.有个要求,需要给其中只包含一个img元素的p标签增加一个叫pic的class.请编写代码实现.可以使用jQuery或KISSY.

    function richText(text) {
        var div = document.createElement('div');
        div.innerHTML = text;
        var p = div.getElementsByTagName('p');
        var i, len;
    
        for (i = 0, len = p.length; i < len; ++i) {
            if (p[i].getElementsByTagName('img').length === 1) {
                p[i].classList.add('pic');
            }
        }
    
        return div.innerHTML;
    }
    

    请实现一个Event类,继承自此类的对象都会拥有两个方法on,off,once和trigger

    function Event() {
        if (!(this instanceof Event)) {
            return new Event();
        }
        this._callbacks = {};
    }
    Event.prototype.on = function (type, handler) {
        this_callbacks = this._callbacks || {};
        this._callbacks[type] = this.callbacks[type] || [];
        this._callbacks[type].push(handler);
    
        return this;
    };
    
    Event.prototype.off = function (type, handler) {
        var list = this._callbacks[type];
    
        if (list) {
            for (var i = list.length; i >= 0; --i) {
                if (list[i] === handler) {
                    list.splice(i, 1);
                }
            }
        }
    
        return this;
    };
    
    Event.prototype.trigger = function (type, data) {
        var list = this._callbacks[type];
    
        if (list) {
            for (var i = 0, len = list.length; i < len; ++i) {
                list[i].call(this, data);
            }
        }
    };
    
    Event.prototype.once = function (type, handler) {
        var self = this;
    
        function wrapper() {
            handler.apply(self, arguments);
            self.off(type, wrapper);
        }
        this.on(type, wrapper);
        return this;
    };
    

    编写一个函数将列表子元素顺序反转

    • 1
    • 2
    • 3
    • 4

    以下函数的作用是?空白区域应该填写什么

    // define
    (function (window) {
        function fn(str) {
            this.str = str;
        }
    
        fn.prototype.format = function () {
            var arg = __1__;
            return this.str.replace(__2__, function (a, b) {
                return arg[b] || '';
            });
        };
    
        window.fn = fn;
    })(window);
    
    // use
    (function () {
        var t = new fn('

    {1}{2}

    '); console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome')); })();

    define部分定义一个简单的模板类,使用{}作为转义标记,中间的数字表示替换目标,format实参用来替换模板内标记 横线处填:

    1. Array.prototype.slice.call(arguments, 0)
    2. /\{\s*(\d+)\s*\}/g

    编写一个函数实现form的序列化(即将一个表单中的键值序列化为可提交的字符串)

    Football Basketball Female Male

    使用原生javascript给下面列表中的li节点绑定点击事件,点击时创建一个Object对象,兼容IE和标准浏览器

    
    
    Object:
    {
        "index": 1,
        "name": "111",
        "link": "http://1111"
    }
    

    script:

    var EventUtil = {
        getEvent: function (event) {
            return event || window.event;
        },
        getTarget: function (event) {
            return event.target || event.srcElement;
        },
        // 返回注册成功的监听器,IE中需要使用返回值来移除监听器
        on: function (elem, type, handler) {
            if (elem.addEventListener) {
                elem.addEventListener(type, handler, false);
                return handler;
            } else if (elem.attachEvent) {
                function wrapper(event) {
                    return handler.call(elem, event);
                };
                elem.attachEvent('on' + type, wrapper);
                return wrapper;
            }
        },
        off: function (elem, type, handler) {
            if (elem.removeEventListener) {
                elem.removeEventListener(type, handler, false);
            } else if (elem.detachEvent) {
                elem.detachEvent('on' + type, handler);
            }
        },
        preventDefault: function (event) {
            if (event.preventDefault) {
                event.preventDefault();
            } else if ('returnValue' in event) {
                event.returnValue = false;
            }
        },
        stopPropagation: function (event) {
            if (event.stopPropagation) {
                event.stopPropagation();
            } else if ('cancelBubble' in event) {
                event.cancelBubble = true;
            }
        }
    };
    var DOMUtil = {
        text: function (elem) {
            if ('textContent' in elem) {
                return elem.textContent;
            } else if ('innerText' in elem) {
                return elem.innerText;
            }
        },
        prop: function (elem, propName) {
            return elem.getAttribute(propName);
        }
    };
    
    var nav = document.getElementById('nav');
    
    EventUtil.on(nav, 'click', function (event) {
        var event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
    
        var children = this.children;
        var i, len;
        var anchor;
        var obj = {};
    
        for (i = 0, len = children.length; i < len; ++i) {
            if (children[i] === target) {
                obj.index = i + 1;
                anchor = target.getElementsByTagName('a')[0];
                obj.name = DOMUtil.text(anchor);
                obj.link = DOMUtil.prop(anchor, 'href');
            }
        }
    
        alert('index: ' + obj.index + ' name: ' + obj.name +
            ' link: ' + obj.link);
    });
    

    有一个大数组,var a = [‘1’, ‘2’, ‘3’, …];a的长度是100,内容填充随机整数的字符串.请先构造此数组a,然后设计一个算法将其内容去重

        /**
        * 数组去重
        **/
        function normalize(arr) {
            if (arr && Array.isArray(arr)) {
                var i, len, map = {};
                for (i = arr.length; i >= 0; --i) {
                    if (arr[i] in map) {
                        arr.splice(i, 1);
                    } else {
                        map[arr[i]] = true;
                    }
                }
            }
            return arr;
        }
    
        /**
        * 用100个随机整数对应的字符串填充数组。
        **/
        function fillArray(arr, start, end) {
            start = start == undefined ? 1 : start;
            end = end == undefined ?  100 : end;
    
            if (end <= start) {
                end = start + 100;
            }
    
            var width = end - start;
            var i;
            for (i = 100; i >= 1; --i) {
                arr.push('' + (Math.floor(Math.random() * width) + start));
            }
            return arr;
        }
    
        var input = [];
        fillArray(input, 1, 100);
        input.sort(function (a, b) {
            return a - b;
        });
        console.log(input);
    
        normalize(input);
        console.log(input);
    

  




  









You can’t perform that action at this time.



You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.










你可能感兴趣的:(面试,面试题)