刷面试题之<<携程 地面业务 前端面试经历>>

在简书看到这篇面试题,结合做者的答案和我的的理解作了一下,因我的水平有限(不谦虚,确实很菜),若是我的作的有什么不对的欢迎指出来,共同交流javascript

做者:诗和元芳
连接:https://www.jianshu.com/p/e6e...
來源:简书
简书著做权归做者全部,任何形式的转载都请联系做者得到受权并注明出处。java

笔试

题目一

<div id="d">
    <div id = "a"></div>
    <div id = "b"></div>
    <div id = "c"></div>
</div>
<script>
    var a = [document.getElementById('a'),document.getElementById('b'),document.getElementById('c')];
    var b = [document.getElementById('d').getElementsByTagName('div')];
</script>
问a 和 b 的区别

咱们把结果打印出来看一下:react

a
es6

b
web

看MDN官方对Element.getElementsByTagName()这个说法的解释:
Element.getElementsByTagName()方法返回一个动态的包含全部指定标签名的元素的HTML集合HTMLCollection。指定的元素的子树会被搜索,不包括元素本身。返回的列表是动态的,这意味着它会随着DOM树的变化自动更新自身。因此,使用相同元素和相同参数时,没有必要屡次的调用Element.getElementsByTagName() .”面试

不少人(包括我和做者)都会觉得这题差异是在b返回的是二维数组,其实都是想固然了。
a返回的是一个包含三个dom元素的数组,而b返回的是只有一个HTMLCollection元素的数组。这是彻底的两种结构且HTMLCollection并不继承自Array.ajax

  • 一、HTMLCollection是及时更新的,当文档中的DOM变化时,它是会随之变化的
  • 二、HTMLCollection能够用 HTMLCollection.item()HTMLCollection.namedItem() 这种方式来获取内部元素。

题目二 数组去重

请手打一个数组去重的方法,题目是[1,2,3,2].distinct() = [1,2,3]。

关于数组去重的方法有不少,网上资料太多再也不赘述,做者用的是一种hash去重的方法。数据库

Array.prototype.distinct = Array.prototype.distinct || function(){
            var len = this.length,
                  i = 0,
                  hash = {},
                  myArr = [];
        for(; i < len; i ++){
                  if(!hash[this[i]]){
                      hash[this[i]] = true;
                      myArr.push(this[i])
                  }
        }
    return myArr;
}

这种方法能够达到题目中的要求,但并非一种严谨的数组去重方式。
假设咱们的的数组变成[1,2,3,2,'1'],这种方法就没法达到去重的效果了,这种方式没法区分数字1和字符串'1',还须要经过类型判断。
关于数组去重,最简单的是ES6的:编程

Array.prototype.distinct = Array.prototype.distinct||function(){
    console.log(this);
    return Array.from(new Set(this)); //return [...(new Set(this))];
}

题目三,考察闭包

function mo(){
    var x = 0;
    return function(){
        console.log(++x)
    }
}
var a = mo();
var b = mo();
a();
a();
b();

答案是1,2,1。
a 和 b是不一样的两个函数,分别保持着各自对不一样的x的引用。canvas

题目四

var p = [];
var A = new Function();
A.prototype = p;
var a = new A;
a.push(1);
console.log(a.length);
console.log(p.length);

答案:1,0。
这题要理解的一点是:

a.__proto__ === p

按照<<高级程序设计>>中讲解的new的过程:

  • 建立一个新对象
  • 将构造函数的做用域赋给新对象(所以this就指向了这个新对象)
  • 执行构造函数中的代码(为这个对象添加属性)
  • 返回新对象

咱们模仿一下new这个过程发生的事:
new A =>

(funciton(){
    //第一步,把__proto__指向p(A.prototype)
    //第二步,按照p(A.prototype)的样子创造一个对象(克隆)
    var a = Object.create(A.protype);
    A.call(a);
    return a;
})()

new 若是在继承对象是没有参数的状况下,是能够不加后面的括号的,编译器会自动替你加上的。可是要记住new的没有括号优先级是低于.的,有括号是高于();

题目五,数组降维

[1,2,3,[4,5,[6,7]]]

下面是做者提供的两种写法:

function fn(arr){ 
    var tempArr = Array.from(arr.join('-'));  //join()会自动添加逗号
    for(var i = 0;i<tempArr.length;i++){ 
        if(isNaN(tempArr[i])){ 
            tempArr.splice(i,1) 
        } 
    } 
    return tempArr; 
}
function fn(arr){
         var myArr = [];
         var fn2 = function(arr2){
               for(var i = 0;i<arr2.length;i++){
                   if(Array.isArray(arr2[i])){
                        fn2.call(null,arr2[i])
                   }
                   else{
                       myArr.push(arr2[i]);
                   }
               }
         }
         fn2(arr);
         return myArr;
       }
       fn([1,2,3,[4,5,[6,7]]]);

这里再提供一种简洁的写法:

let flatten = arr => arr.reduce((pre,cur)=>{
    Array.isArray(cur)?pre.push(...flatten(cur)):pre.push(cur);
    return pre
},[])

面试

函数声明和函数表达式有什么区别

答:解析器有一个函数声明提高的过程,读取并将函数声明添加到执行环境中,Javascript在第一遍会声明函数并将它们放到源代码的顶部。使其在执行任何代码以前可用。

函数声明既然会提高,优先级是什么,和var比呢

答:函数提高优先级比变量提高要高,且不会被变量声明覆盖,可是会被变量赋值覆盖,也会被后面的同名函数替换。

console.log(typeof(foo));   //function
function foo(){}
var foo = 5;
foo = 5;
console.log(typeof(foo));  //number
function foo(){}

函数声明的提高为何会比var高,编译器干了什么事情

引擎在执行javascript代码以前,会先将其进行编译,编译阶段会找到全部声明,并找到合适的做用域将它们关联起来。
Javascript在第一遍会声明函数并将它们放到源代码的顶部
函数声明提高的是整个函数,变量声明提高的仅仅是var a;这部分。

函数声明会将变量声明覆盖,而变量声明只能当作重复声明被忽略。因此函数声明的提高比var高。(纯我的理解,若有不对欢迎指出)

es6 装饰器用过没,是干什么用的(应该是es7的,反正我也没答出来,答出来确定还继续深的问)

装饰类、装饰方法或属性。装饰器能够联想到装饰器模式:向一个现有的对象添加新的功能,同时又不改变其结构的设计模式,它是做为现有的类的一个包装。

es6中的扩展运算符...的实现原理

调用默认的iterator接口

<-------------------如下内容明天接着刷---------------------------->

es6中的解构中的...和上面的区别

答:说真的,我也不知道啥区别,不是同样用吗?

[...org,name] = [1,2,3,4] 这样的话,org里是个啥

答:开始问的放后面是啥,我想了半天,没敢说,我说难道后面的就没抓到,全被org抓走了?其实不是,直接报错了,...是rest的意思,既然是rest,那就只能放在最后啊

更新说明我还不会用,区别应该是问的es7中的解构。原理就是es6直接采用for of,也就是说,全部总有迭代器的对象都能使用扩展运算符,在es6里说不能放前面的,可是在es7里若是用于对象是能够放前面的。懂了这个,上面几题就都该会了

for of 和for in区别

答:for in 是键值对形式,for of 是输出value形式,而后for of只要是配置了迭代器,都能遍历。

this的指向问题

答:这个正常的都说了

箭头函数中的this

答:这里说的很差,我只说了用了箭头函数的话,this就被传进来了。就不须要绑定进来了。

箭头函数中的this默认指向在定义它时,它所处的对象,而不是执行时的对象, 定义它的时候,可能环境是window

什么是闭包(这里答的不太好,虽然都会用啊处理的,我用相似以下代码举例,貌似面试官并不满意...)

function aa(){
        var a = 1;
        return function bb(){
            console.log(a);
        }
    }
    aa()()

什么是做用域

答:在进入脚本标签编译阶段的时候就定义了各种做用域,外面的变量就在全局做用域,函数内部的就在函数的做用域里,做用域外的函数不能访问某个做用域里面的东西

什么是做用域链

答:在各级执行上下文建立阶段的时候,就肯定了各级做用域,串起来就是做用域链了。好比闭包的时候外部函数出栈以后,内部函数还保留了对外部函数某个变量的引用,就是经过做用域链找过去的

什么是原型

答:prototype,好像我也说不出啥,就举个函数的写原型的例子。
js有哪些设计模式(我说有工厂模式,构造函数模式,原型模式,面试官说这是面向对象,不过我以为有啥区别,面向对象编程不久是要用这些设计模式吗)
这些模式都是咋写的,我手写给他看

为何要用原型

答:共享原型里的东西给下属继承的对象,这样在new的时候不用从新建立,节省内存空间

eval的缺点

答:我说了用法,就是可执行string,而后缺点没说,没怎么研究,只是看了一眼用法类型的

with的缺点

答:没用过,在网上看到过,说不要用,而后我就不用,应该会致使性能问题吧

在严格模式下能不能用eval

答:不能

es5和es6严格模式的区别

答:不知道

什么是柯里化,举React和Redux的例子

答:解释了柯里化是啥,举不出来例子,没看过源码啊或者是对react了解的不够多

什么是纯函数

答:不产生任何交互的函数?答的很差,我说reducer应该就是个纯函数,猜对了而已。

纯函数是指 不依赖于且不改变它做用域以外的变量状态 的函数纯函数的概念连接

页面和服务器之间的交互有哪几种(ajax,websocket,不满意)

ajax的Type有几种(我只知道post和get)

这题我可能没有理解...
get和post的区别(我说的表象区别,url参数,安全性,大小限制,面试官不是很满意)

与 POST 相比,GET 更简单也更快,而且在大部分状况下都能用。
然而,在如下状况中,请使用 POST 请求:
没法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

HTTP请求头上都有什么信息

答:UA,HOST,其余的我也没说,就说还有几个没注意..

如何统计页面上的按钮被点击了多少次

答:和服务器交互?反正也只能存服务器啊...

单页面应用和多页面应用的区别

答:一个跳页面是内部的,一个跳页面是href整页刷新的。

哪一种更容易被SEO到,优化SEO

答:猜想是多页面,页面多呗...优化的不知道

上两题补充连接

cookie和localstorage区别(我说大小,安全,有效期,貌似又不是很满意)

JSON.stringify(大OBJ)的时候会有什么问题
答:性能损失。

script标签顺序怎么控制,涉及到依赖必需要有前后

答:在HTML层就控制顺序呗,显然不是他要的答案

除了直接引用script标签,若是不用import require这样的东西,怎么调用其它页面的js

答:真不知道,a.js里除了用script标签引用b.js

import和require的区别

答:import是静态加载,一旦你import,内容就进来了,require是动态加载,用的时候才加载,后面又问了一些,后面就不会了

函数节流怎么实现

答:简单是settimeout,时间超出就执行,没超出再进来的话就直接clear掉。面试官以为太简单了。

canvas 绘制原理

答:不知道

如何使用canvas拖动一个小球撞击另一个小球,而后另一个小球被撞击出去
答:canvas一年半没用铁定不记得了(总共也就2年经验),可是说了一下实现思路

canvas 里有不少小球时如何优化性能

答:不知道

微信小程序跳转页面最多能跳转多少层 不会

RN中listview 的key值的实现原理 不会

而后还问了一些关于项目上的问题,以及如何设计一个搜索组件,须要考虑到哪些问题。应该就这些,没想起来的想起来再补充,感受答的很差,不少都不记得了。三分之一的题目 好比实现原理啊,缺点啊,为何啊,会有什么问题啊,此类问题要么不会,要么答的很差总共就这么多,我要继续巩固基础了~!!!!!!!

相关文章
相关标签/搜索