原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questions.mdjavascript
最近将持续翻译JavaScript面试题,但愿对各位有所帮助。 html
(文章中斜体字部分为译者添加)java
目录:
Part 1(事件委托/this关键字/原型链/AMD与CommonJS/自执行函数)git
变量未声明 是指给一个变量赋值时,没有使用var,let,const关键字对变量进行声明。未声明的变量会被默认定在全局,而非当前做用域中。在严格模式中,试图给一个未声明的变量赋值时,JS会抛出ReferenceError的异常。就像要避免滥用全局变量同样,咱们一样要避免操做未声明的变量。能够在操做变量时加入try/catch来捕获未声明的变量异常。编程
1 function foo() { 2 x = 1; // 在严格模式下将会抛出异常:ReferenceError 3 } 4 5 foo(); 6 console.log(x); // 1
undefined变量则是指一个变量被声明,可是未被赋值。这种变量的类型也是 undefined。若是将一个没有返回值的函数执行结果赋值给一个变量的话,这个变量值也会是undefined。若是判断一个变量值是否是undefined呢?可使用typeof 判断返回值是否是恒等于(===)字符串 "undefined"。这里要注意,不能使用双等号判断变量是否等于undefined,由于用null去判断的话也会返回true。(原文意思是 null == undefined 返回的值也是true)数组
1 var foo; 2 console.log(foo); // undefined 3 console.log(foo === undefined); // true 4 console.log(typeof foo === 'undefined'); // true 5 6 console.log(foo == null); // true. 不能这么去判断,结果不许确 7 8 function bar() {} 9 var baz = bar(); 10 console.log(baz); // undefined
null值变量是指一个变量被赋值为null。虽然null的表面意思是空值,可是它和undefined是彻底不同的,由于它已经被赋值过了。若是判断null值?最简单的方法就是用恒等于进行判断。一样要注意的是,这里也不能使用双等号来判断,缘由和上面同样,由于undefined判断也会返回true。 闭包
1 var foo = null; 2 console.log(foo === null); // true 3 4 console.log(foo == undefined); // true.不能这么去判断,结果不许确
我有一个我的习惯,就是不会让变量出现未声明或者未赋值的状况。我会在变量声明的同时给它赋值为null,哪怕这个变量后续再也不使用。 架构
引用文档:
https://stackoverflow.com/questions/15985875/effect-of-declared-and-undeclared-variables
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/undefined
闭包是函数和声明该函数的词法环境的组合。这里的语法其实是指语法做用域使用一个变量的位置就是声明该变量的位置。闭包函数拥有访问外部函数变量的能力,哪怕外部函数已经执行完毕。(因为闭包会使得函数中的变量都被保存在内存中,内存消耗很大,因此不能滥用闭包,不然会形成网页的性能问题,在IE中可能致使内存泄露)
为何要使用闭包?
引用文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36
为了方便理解这两个方法,让咱们分别来看这两个方法的功能。
forEach
1 const a = [1, 2, 3]; 2 const doubled = a.forEach((num, index) => { 3 // Do something with num and/or index. 4 }); 5 6 // doubled = undefined
map
1 const a = [1, 2, 3]; 2 const doubled = a.map(num => { 3 return num * 2; 4 }); 5 6 // doubled = [2, 4, 6]
因此这两个方法最主要的区别就在于map会返回一个新数组。若是你须要接收处理结果,而且不修改原始数组,那么map就是最合适的选择。若是你只是但愿单独循环一个数组的元素,那么forEach能够胜任。
引用文档:
https://codeburst.io/javascript-map-vs-foreach-f38111822c0f
能够用在自执行函数中。自执行函数包含一些代码在本地做用域中,这样变量就被声明在本地做用域中,而不会污染全局变量。
1 (function() { 2 // Some code here. 3 })();
做为一次性使用的回调函数,不须要在其余地方继续使用该函数。将回调函数定义在代码的右侧,这样的代码看起来总体性与可读性比较好,同时也不用处处去查找函数的实现体。
1 setTimeout(function() { 2 console.log('Hello world!'); 3 }, 1000);
做为函数式变成构造器或者Lodash的参数。
1 const arr = [1, 2, 3]; 2 const double = arr.map(function(el) { 3 return el * 2; 4 }); 5 console.log(double); // [2, 4, 6]
引用文档:
https://www.quora.com/What-is-a-typical-usecase-for-anonymous-functions
之前,我用Backbone来建立个人数据模型,它鼓励使用面向对象的思想,先建立Backbone模型,而后在把方法加上去。
虽然组件模式仍然很棒,但时至今日,我开始使用基于React/Redux的Flux架构,这是一种鼓励单向数据流动的函数式编程方式。我将使用普通对象来做为model层,而后写一些纯工具类的方法来管理这些对象。和其余的Redux程序同样,State经过actions和reducers来进行维护,
另外我会尽可能避免使用传统的继承。若是非要用,我也会遵循如下规则:these rules