在简书看到这篇面试题,结合做者的答案和我的的理解作了一下,因我的水平有限(不谦虚,确实很菜),若是我的作的有什么不对的欢迎指出来,共同交流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的过程:
咱们模仿一下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在第一遍会声明函数并将它们放到源代码的顶部。使其在执行任何代码以前可用。
答:函数提高优先级比变量提高要高,且不会被变量声明覆盖,可是会被变量赋值覆盖,也会被后面的同名函数替换。
console.log(typeof(foo)); //function function foo(){} var foo = 5;
foo = 5; console.log(typeof(foo)); //number function foo(){}
引擎在执行javascript
代码以前,会先将其进行编译,编译阶段会找到全部声明,并找到合适的做用域将它们关联起来。
Javascript在第一遍会声明函数并将它们放到源代码的顶部
函数声明提高的是整个函数,变量声明提高的仅仅是var a
;这部分。
函数声明会将变量声明覆盖,而变量声明只能当作重复声明被忽略。因此函数声明的提高比var高。(纯我的理解,若有不对欢迎指出
)
装饰类、装饰方法或属性。装饰器能够联想到装饰器模式:向一个现有的对象添加新的功能,同时又不改变其结构的设计模式,它是做为现有的类的一个包装。
调用默认的iterator接口
<-------------------如下内容明天接着刷---------------------------->
答:说真的,我也不知道啥区别,不是同样用吗?
答:开始问的放后面是啥,我想了半天,没敢说,我说难道后面的就没抓到,全被org抓走了?其实不是,直接报错了,...是rest的意思,既然是rest,那就只能放在最后啊
更新说明我还不会用,区别应该是问的es7中的解构。原理就是es6直接采用for of,也就是说,全部总有迭代器的对象都能使用扩展运算符,在es6里说不能放前面的,可是在es7里若是用于对象是能够放前面的。懂了这个,上面几题就都该会了
答:for in 是键值对形式,for of 是输出value形式,而后for of只要是配置了迭代器,都能遍历。
答:这个正常的都说了
答:这里说的很差,我只说了用了箭头函数的话,this就被传进来了。就不须要绑定进来了。
箭头函数中的this默认指向在定义它时,它所处的对象,而不是执行时的对象, 定义它的时候,可能环境是window
function aa(){ var a = 1; return function bb(){ console.log(a); } } aa()()
答:在进入脚本标签编译阶段的时候就定义了各种做用域,外面的变量就在全局做用域,函数内部的就在函数的做用域里,做用域外的函数不能访问某个做用域里面的东西
答:在各级执行上下文建立阶段的时候,就肯定了各级做用域,串起来就是做用域链了。好比闭包的时候外部函数出栈以后,内部函数还保留了对外部函数某个变量的引用,就是经过做用域链找过去的
答:prototype,好像我也说不出啥,就举个函数的写原型的例子。
js有哪些设计模式(我说有工厂模式,构造函数模式,原型模式,面试官说这是面向对象,不过我以为有啥区别,面向对象编程不久是要用这些设计模式吗)
这些模式都是咋写的,我手写给他看
答:共享原型里的东西给下属继承的对象,这样在new的时候不用从新建立,节省内存空间
答:我说了用法,就是可执行string,而后缺点没说,没怎么研究,只是看了一眼用法类型的
答:没用过,在网上看到过,说不要用,而后我就不用,应该会致使性能问题吧
答:不能
答:不知道
答:解释了柯里化是啥,举不出来例子,没看过源码啊或者是对react了解的不够多
答:不产生任何交互的函数?答的很差,我说reducer应该就是个纯函数,猜对了而已。
纯函数是指 不依赖于且不改变它做用域以外的变量状态 的函数纯函数的概念连接
页面和服务器之间的交互有哪几种(ajax,websocket,不满意)
这题我可能没有理解...
get和post的区别(我说的表象区别,url参数,安全性,大小限制,面试官不是很满意)
与 POST 相比,GET 更简单也更快,而且在大部分状况下都能用。
然而,在如下状况中,请使用 POST 请求:
没法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
答:UA,HOST,其余的我也没说,就说还有几个没注意..
答:和服务器交互?反正也只能存服务器啊...
答:一个跳页面是内部的,一个跳页面是href整页刷新的。
答:猜想是多页面,页面多呗...优化的不知道
上两题补充连接
cookie和localstorage区别(我说大小,安全,有效期,貌似又不是很满意)
JSON.stringify(大OBJ)的时候会有什么问题
答:性能损失。
答:在HTML层就控制顺序呗,显然不是他要的答案
答:真不知道,a.js里除了用script标签引用b.js
答:import是静态加载,一旦你import,内容就进来了,require是动态加载,用的时候才加载,后面又问了一些,后面就不会了
答:简单是settimeout,时间超出就执行,没超出再进来的话就直接clear掉。面试官以为太简单了。
答:不知道
如何使用canvas拖动一个小球撞击另一个小球,而后另一个小球被撞击出去
答:canvas一年半没用铁定不记得了(总共也就2年经验),可是说了一下实现思路
答:不知道
RN中listview 的key值的实现原理 不会
而后还问了一些关于项目上的问题,以及如何设计一个搜索组件,须要考虑到哪些问题。应该就这些,没想起来的想起来再补充,感受答的很差,不少都不记得了。三分之一的题目 好比实现原理啊,缺点啊,为何啊,会有什么问题啊,此类问题要么不会,要么答的很差总共就这么多,我要继续巩固基础了~!!!!!!!