前方端面试题和答案整理(一)

各国公司秋招很快即开了,最近当备面试的物,干脆将发现的个面试题整理一下共享出来,大部分面试题是从来不标准答案的,我为出之答案为是单纯供参考,如果产生重新好的解答欢迎在评论区留言。

Part1 手写代码

当场手写代码是现行面试中很普遍的一类面课题,考察基础之数据结构与算法能力。

1 数组去再的实现

  • 基本数组去又

    Array.prototype.unique = function(){

    var result = [];
    this.forEach(function(v){
        if(result.indexOf(v) < 0){
            result.push(v);
        }
    });
    return result;
    

    }

  • 动用hash表去重新,这是平等栽空间更换时间之艺术

    Array.prototype.unique = function(){

    var result = [],hash = {};
    this.forEach(function(v){
        if(!hash[v]){
            hash[v] = true;
            result.push(v);
        }
    });
    return result;
    

    }

面的不二法门有一个bug,对于数组[1,2,’1′,’2′,3],去再结果吗[1,2,3],原因在于对象对属于性索引时会展开强制类型转换,arr[‘1’]和arr[1]获取的且是arr[1]的价值,因此用开片改变:

Array.prototype.unique = function(){
    var result = [],hash = {};
    this.forEach(function(v){
        var type = typeof(v);  //获取元素类型
        hash[v] || (hash[v] = new Array());
        if(hash[v].indexOf(type) < 0){
            hash[v].push(type);  //存储类型
            result.push(v);
        }
    });
    return result;
}
  • 先期排序后错过再

    Array.prototype.unique = function(){

    var result = [this[0]];
    this.sort();
    this.forEach(function(v){
        v != result[result.length - 1] && result.push(v); //仅与result最后一个元素比较
    });
    

    }

  • 利用ES6 Set去重

    //ES6环境下
    Array.prototype.unique = function(){
         return [...new Set(this)];
    }
    

2 快速排序的贯彻

方一致(尽可能不要js数组方法):

function quickSort(arr){
    qSort(arr,0,arr.length - 1);
}
function qSort(arr,low,high){
    if(low < high){
        var partKey = partition(arr,low,high);
        qSort(arr,low, partKey - 1);
        qSort(arr,partKey + 1,high);
    }
}
function partition(arr,low,high){
    var key = arr[low];  //使用第一个元素作为分类依据
    while(low < high){
        while(low < high && arr[high] >= arr[key])
            high--;
        arr[low] = arr[high];
        while(low < high && arr[low] <= arr[key])
            low++;
        arr[high] = arr[low];
    }
    arr[low] = key;
    return low;
}

术二(使用js数组方法):

function quickSort(arr){
   if(arr.length <= 1) return arr;
   var index = Math.floor(arr.length/2);
   var key = arr.splice(index,1)[0];
   var left = [],right = [];
   arr.forEach(function(v){
       v <= key ? left.push(v) : right.push(v);
   });
   return quickSort(left).concat([key],quickSort(right));
}

此外假如明白,快速排序的平分日复杂度O(nlogn),最要命情况是平稳的情事,时间复杂度为n的平方,另外快速排序是休安静之。

Part2 JavaScript相关

1 JavaScript基础数据类型

JavaScript数据类型包括原始类型和援类型,原始类型有五只:

  Number(数值) String(字符串) Boolean(布尔) Null(空) Undefined(未定义)

援类型有一个:

 Object(对象)

通过typeof(x)可回一个变量x的数据类型“number”、“string”、“boolean”、“undefined”、”object”,这里而留意一点:typeof运算符对于null类返回的是object

《JavaScript高级程序设计》:
随即其实是JavaScript最初实现中的一个错误,后来被ECMAScript沿用了。现在null被当是目标的占位符,从而解释了当时同样抵触。但是由技术及的话,它仍是原始值。

2 谈一谈JavaScript作用域链

当执行同一截JavaScript代码(全局代码或函数)时,JavaScript引擎会创造为夫缔造一个作用域又叫做执行上下文(Execution
Context),在页面加载后会率先创建一个大局的作用域,然后每执行一个函数,会建立一个相应之作用域,从而形成了同样久作用域链。每个作用域都来一致长达对应的意域链,链头是大局作用域,链尾是时下函数作用域。

图域链的作用是用来解析标识符,当函数被创造时(不是执行),会以this、arguments、命名参数与该函数惨遭之享有有变量添加至拖欠当前企图域中,当JavaScript需要找变量X的时候(这个过程叫变量解析),它首先会见于图域链中之链尾也就是目前作用域进行搜索是否生X属性,如果无找到就沿着作用域链继续查找,直到查找到链头,也不怕是大局意图域链,仍不找到该变量的话,就觉得这段代码的意图域链上无设有x变量,并丢掉来一个援错误(ReferenceError)的生。

3 如何知道JavaScript原型链

JavaScript中之每个对象都来一个prototype性能,我们叫原型,而原型的值也是一个对象,因此她吗发生温馨的原型,这样虽串联起了相同长达原型链,原型链的链头是object,它的prototype比较特殊,值也null。

原型链的打算是用来对象继承,函数A的原型属性(prototype
property)是一个对象,当是函数被用作构造函数来创造实例时,该函数的原型属性将被当作原型赋值给所有目标实例,比如我们新建一个频组,数组的主意就由数组的原型上此起彼伏而来。

当访问对象的一个属性时, 首先查找对象自我, 找到则赶回; 若未找到,
则继续查找其原型对象的性能(如果还摸索不交骨子里还见面顺原型链向上查找,
直至到根). 只要没有受覆盖的语,
对象原型的属性就会当具有的实例中找到,若一切原型链未找到则返回undefined;

4 JavaScript变量声明提前

《JavaScript权威指南》中凡这样说明的:JavaScript变量在宣称前曾经可用,JavaScript的这特性深受非正式的名声明提前(hoisting),即JavaScript函数中声明的兼具变量(但不涉及赋值)都被“提前”至函数的顶部。

由一个例证来拘禁:

var scope = "global";
function myFunc(){
    console.log(scope); 
    var scope = "local";
}

控制台打印出来的不是“global”而是“undefined”,这是因于myFunc这个函数的图域中,局部变量scope声明被提前交函数顶部,而此时,scope仅宣称,未赋值,因此输出undefined。实际上,上面的代码和底的功能是同样的:

var scope = "global";
function myFunc(){
    var scope;
    console.log(scope);
    scope = "local";
}

5 如何掌握和运JavaScript闭包

至于闭包具体的概念文献中给的定义充分虚幻,我觉得闭包是一模一样种植如函数能够还去其它函数的组成部分变量的语法机制。

推个例子:

function outFunc(){
    var name = "Vicfeel";
    function inFunc(){
        console.log(name);
    }
    return inFunc;
}
inFunc(); //控制台显示"Vicfeel"

立马是事例我们得以看到,在函数inFunc中依然得以访问outFunc的片变量name。

闭包应用举例,模拟类的个人属性,利用闭包的性质,局部变量只有当sayAge方法被才可拜,而name在表为看,从而实现了看似的私房属性。

    function User(){
        this.name = "Vicfeel";  //共有属性
        var age = 23;    //私有属性
        this.sayAge:function(){
            console.log("my age is " + age); 
        }
    }
    var user = new User();
    console.log(user.name); //"Vicfeel"
    console.log(user.age);  //"undefined"
    user.sayAge();   //"my age is 23"

而打听详细的闭包,推荐一下
阮一峰的网络日志-学习Javascript闭包(Closure)。

6 new构建对象的本质

    function User(){
        this.name = "Vicfeel";
        this.age = 23;
    }

    var user = new User();

透过new操作符,实际上在构造函数User中成就了之类操作:

  • 创建一个初的对象,这个目标的类是object;
  • 安这个新的目标的中、可访问性和prototype属性为构造函数(指prototype.construtor所针对的构造函数)中设置的;
  • 实施构造函数;
  • 回去新创建的对象。

    function User(){
        //this = {};  
        //this.constructor = User;
        this.name = "Vicfeel";
        this.age = 23;
        //return this;
    }
    
    var user = new User();
    

比方构造函数默认返回的初创的this对象,如果手动return
一个变量的话,如果该变量是原始类型则不行,如果是目标,则赶回该对象。

7 JavaScript代理

当我们得对过剩素添加事件的下,可以由此将事件续加到它们的父节点而将事件委托给父节点来点处理函数。

比如我们用向一个ul中动态增长很多个li,需要遍历li逐个上加点击事件

    <ul id='list'></ul>

    var count = 100;
    var ulList = document.getElementById("list");
    //动态构建节点
    for(var i = count;i--;){
        var liDom = document.createElement('li');
        ulList.appendChild(liDom);
    }
    //绑定点击事件
    var liNode = ulList.getElementByTagName("li");
    for(var i=0, l = liNodes.length; i < l; i++){
        liNode[i].onClick = function(){
            //li点击事件
        }
    }   

阳,DOM操作是可怜消耗性能的。所以再次的轩然大波绑定简直是性质杀手。而事件代理的核心思想,就是通过尽量少的绑定,去监听尽量多的事件。如何做啊?答案是行使事件冒泡机制,对该父节点ul进行事件绑定(Event
Bubble),然后通过event.target来判定是孰节点触发的波,从而减少过多EventHandler的绑定。

    var count = 100;
    var ulList = document.getElementById("list");
    //动态构建节点
    for(var i = count;i--;){
        var liDom = document.createElement('li');
        ulList.appendChild(liDom);
    }
    //绑定点击事件
    var liNode = ulList.getElementByTagName("li");
    liNode.onClick = function(e){
        if(e.target && e.target.nodeName.toUpperCase == "LI") {
            // li点击事件
        }
    }

察觉新内容会连更新…

博文作者:vicfeel
博文出处:http://www.cnblogs.com/vicfeel
本文版权归作者和博客园共有,欢迎转载,但得保留这个段子声明,并为来本和链接,谢谢合作!
假定看了本文章,觉得有帮,您可以吧自己的博文点击“推荐一下”!