刷 携程 地面业务 前端面试经历

栏目: JavaScript · 发布时间: 5年前

内容简介:在简书看到这篇面试题,结合作者的答案和个人的理解做了一下,因个人水平有限(不谦虚,确实很菜),如果个人做的有什么不对的欢迎指出来,共同交流作者:诗和元芳 链接:问a 和 b 的区别

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

作者:诗和元芳 链接: www.jianshu.com/p/e6efcd993… 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

笔试

题目一

<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 的区别

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

a

刷 携程 地面业务 前端面试经历

b

刷 携程 地面业务 前端面试经历

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

很多人(包括我和作者)都会以为这题差别是在b返回的是二维数组,其实都是想当然了。 a返回的是一个包含三个dom元素的数组,而b返回的是只有一个 HTMLCollection 元素的数组。这是完全的两种结构且 HTMLCollection 并不继承自 Array .

  • 1、 HTMLCollection 是及时更新的,当文档中的DOM变化时,它是会随之变化的
  • 2、 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的引用。

题目四

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年经验),但是说了一下实现思路


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据分析技术白皮书

数据分析技术白皮书

伍海凤、刘鹏、杨佳静、马师慧Sara、李博、Shirley Song、Zinc、李晓艳 / 2016-8-11 / 0

关于数据分析技术白皮书(Analytics Book 中文版),主要内容围绕: 1. 分析(Analytics):网站分析 & APP分析 2. 谷歌分析工具的原理、部署与使用 3. 开源网站分析工具的原理、部署与使用 4. Log日志分析原理 5. 网站分析的维度与指标定义 6. 如何炼成为一个互联网数据分析师 请访问书的数据分析技术白皮书官网“免费”阅......一起来看看 《数据分析技术白皮书》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具