app网站建设哪家好,视频拍摄剪辑培训,五金配件东莞网站建设技术支持,科技公司网站源码1.用typeof bar”object”判断bar是否是一个object的潜在缺陷是什么#xff1f;怎样才能避免这种缺陷#xff1f; 答#xff1a;尽管用typeof bar”object”是一个判断bar是一个object的可靠方法#xff0c;但是令人惊讶的是#xff0c;在JavaScript中null也是一个object!… 1.用typeof bar”object”判断bar是否是一个object的潜在缺陷是什么怎样才能避免这种缺陷 答尽管用typeof bar”object”是一个判断bar是一个object的可靠方法但是令人惊讶的是在JavaScript中null也是一个object! 因此以下的代码会让很多开发者惊讶log显示true而不是false. var bar null; console.log(typeof bar object); // logs true! 只要你意识到这些这个问题就能通过判断bar是否为null轻松避免 console.log((bar ! null) (typeof bar object)); // logs false 为了使我们的答案更加完全、彻底的解决这个问题还有两件事需要说明 首先上面的解决方案里如果bar是一个function也会返回false,通常情况下这是我们期望的但是在某些情况下我们希望当bar是function时也返回true,你就需要修改上面的解决方案如下 console.log((bar ! null) ((typeof bar object) || (typeof bar function))); 其次如果bar是一个array(var bar[])也会返回true,大多情况下这是我们想要的结果因为arrays的确是objects。但是如果当bar为arrays你想返回false你就需要修改上面的解决方案如下 console.log((bar ! null) (typeof bar object) (toString.call(bar) ! [object Array])); 或者用jQuery如下 console.log((bar ! null) (typeof bar object) (! $.isArray(bar))); 2.下面的代码将输出什么并说明原因 (function(){ var a b 3; })(); console.log(a defined? (typeof a ! undefined)); console.log(b defined? (typeof b ! undefined)); 答既然a和b在一个function的代码块里定义并且既然在同一行以var开始很多JavaScript开发者认为typeof a和typeof b都将是undefined.然而事实却并非如此大多数开发者的问题是错误的理解了var ab3;这段代码以为是下面代码的缩写: Var b3; Var ab; 但是事实上var ab3; 实际缩写是以下代码 b3; Var ab; 如果你没有采用strict模式,输出结果如下 a defined? false b defined? True 但是b在function的内部怎么在外部是defined呢? 好吧既然var ab3;是b3和var ab;的缩写b最终是作为全局变量的因为b没有用var定义因此作用域在function外部。 需要注意的是在strict 模式如使用use strictvar ab3;将会产生一个运行时errorReferenceError: b is not defined。因此可以避免这类的错误。因此这也使为什么要在你的代码应采用use strict模式。 3.以下代码的输出是什么并说明原因。 var myObject { foo: bar, func: function() { var self this; console.log(outer func: this.foo this.foo); console.log(outer func: self.foo self.foo); (function() { console.log(inner func: this.foo this.foo); console.log(inner func: self.foo self.foo); }()); } }; myObject.func(); 答上面的代码输出如下 outer func: this.foo bar outer func: self.foo bar inner func: this.foo undefined inner func: self.foo bar 在outer function里this和self都指向myObject, 因此都能访问到foo, 在inner function里this不再指向myObject,因此this.foo在inner function里面是undefined,然而self依然指向myObject在ECMA5之前this在内部function里将指向window然而在ECMA5之后内部function的this将是undefined). 4.将一个JavaScript文件封装在一个function块里的意义原因是什么 答在很多流行的JavaScript库jQuery,Node.js等将源码文件封装在一个函数中越来越普遍。这种技术会为这个源码文件创建一个封闭的环境可能最重要的是创建了一个私有的命名空间因此避免了在不同的JavaScript modules和库中出现潜在的命名冲突。 这种技术的另一个特点是允许通过别名的方式很容易的引用全局变量。这个经常用到比如在jQuery插件中jQurey 允许你通过jQuery.noConflict(),使得不能通过$引用jQuery命名空间。如果你这么做了你依然可以像下面代码一样使用$采用这种闭包的技术 (function($) { /* jQuery plugin code referencing $ */ } )(jQuery); 5.在JavaScript源码文件中以’use strict’开始的意义和好处是什么 答采用strict模式的主要好处如下 a.使得debugging更容易在一些被忽略或者潜在的错误会产生error或者exceptions会很快的在你的代码中显示警告引导你很快的找到对应的源码。 b.阻止出现意外的全局变量如果不是在strict模式里那么赋值给一个没有声明的变量时会自动的创建一个同名的全局变量这是JavaScript中最常见的错误之一。在strict模式里会尝试抛出一个error. c.强制排除this错误在非strict模式里this引用为null或者undefined时会自动强制指向全局这会导致各种错误的引用。在strict模式里this值为null或者undefined将会抛出error. d.不允许重名的属性名或者参数名.在strict模式里如果定义了如var object{foo:’bar’,foo:’baz’};或者定义一个重名参数的函数如:function foo(val1,val2,val1){}.会产生一个error,而这个bug几乎一定会产生但你可能浪费大量的时间才能找到。 e.使eval()更加安全。在strict模式和非strict模式里eval()存在很多不同。在strict模式里变量和函数在eval()中声明但语句不在内部块创建但是在非strict模式里语句也会在内部块里创建这也是常见的源码问题。 f.不正确使用delete会抛出error:delete操作用于从object中删除一个属性不能用于没有配置的属性在非strict模式的代码里删除一个没有配置的属性会失败但不会有提示在strict模式里则会抛出error。 6.考虑一下下面的两个函数他们将返回同样的值吗请说明原因 function foo1() { return { bar: hello }; } function foo2() { return { bar: hello }; } 答很奇怪的是两个函数返回的值并不一样如果执行以下语句 console.log(foo1 returns:); console.log(foo1()); console.log(foo2 returns:); console.log(foo2()); 将得到下面的结果 foo1 returns: Object {bar: hello} foo2 returns: undefined 不仅仅只是对返回不一样的结果奇怪也要对foo2()没有抛出error特别注意。产生这个结果的原因是分号在JavaScript中的用法省略分号不是好的做法。当foo2()的一行语句中只包含return时会在return语句后面自动的加上一个分号。后面的语句也是合法的不会抛出error尽管它不会调用也不做任何事仅仅只是一个没有用到的语句块它定义了一个等同于’hello’字符串的属性bar而已。 这也说明了在Javascript中大括号的位置应该放在语句后面的编程风格更符合Javascript的语法要求有些语言推荐放在新一行的开头。 7.NaN是什么它是什么类型怎样能够可靠的判断一个值是否等于Nan? 答NaN表示一个值不少number一般指一个操作中有一个非number的值或者操作的结果是非number的值例如被0除。这看起来很清楚明了然而对于Nan如果不了解的话会有两个很奇怪的特性会让人头疼。 一个是尽管NaN的意思是不是number,但NaN的类型是number,如下 console.log(typeof NaN number); // logs true 另外一个是NaN更任何东西比较即使是自身结果都为false,如下 console.log(NaN NaN); // logs false。 用isNaN()判断一个number是否等于NaN是不可靠的更好的解决方案使用value!value这个只有当value等于NaN时才会为true.在ES6中可以用Number.isNaN()来判断比使用老的全局函数isNaN()更可靠。 8.下面的代码输出结果是什么并解释原因 console.log(0.1 0.2); console.log(0.1 0.2 0.3); 答这个问题也可以解释为你可能很有信心它将打印0.3和true然而可能是错的在JavaScript中数字采用浮点计数因此常常并不是期望的值。上面的例子将打印以下结果 0.30000000000000004 False 9.讨论一下怎样写一个函数isInteger(x)判断x是一个整数。 答这听起来并不重要事实上在ES6中有一个新的函数Number.isInteger()能准确的实现这个目的然而在ES6之前就比较复杂没有如Number.isInteger()的方法。 这个问题主要是因为在ECMAScript中,整形只是概念上的数字都是采用浮点计数。出于这个考虑在ES6中的解决方式采用的是最简单的方式function isInteger(x) { return (x^0) x; } 。 下面的方案也可以尽管没有上面的优雅。 function isInteger(x) { return Math.round(x) x; } 用Math.ceil()或者Math.floor()代替Math.round()也可以。 还可以选择 function isInteger(x) { return (typeof x number) (x % 1 0); } 通常采用下面的方案是不正确的。 function isInteger(x) { return parseInt(x, 10) x; } 这主要是因为parseInt是基于能正确转化x一旦x太大它会转换失败parseInt会在转化成数字是先强制转换为字符串因此一旦一个数字太大它转化的字符串是原数字的指数形式1e21因此parseInt()将会解析1e21,但是当遇到e是会停止解析了。如下 String(1000000000000000000000) 1e21 parseInt(1000000000000000000000, 10) 1 parseInt(1000000000000000000000, 10) 1000000000000000000000 False 10.下面数字1-4的打印顺序是什么并解释原因。 (function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })(); 答上面的结果应该是 1 4 3 2 让我们预测一下每一部分的代码 A.1和4将在调用console.log()后直接打印出来。 B.2在3之后打印因为3没有时间延迟2在3打印后延迟了1000毫秒在打印。 但是3延迟时间为0难道不意味着立即打印吗并且如果这样3应该在4之前打印应为打印4的代码在后面执行的。这个问题的答案需要好好理解JavaScript的events和timing. 浏览器有一个事件队列用来检查处理和等待事件。例如当一个事件在后台触发了例如onload然而现在浏览器很忙在处理onclick这个事件会放入事件队列中当onclick句柄完成后会检查事件队列执行事件(onload)。 类似如果浏览器忙则setTimeout()会将执行的函数放入事件队列中。当setTimeout()设置时间为0它的意思是“尽可能快”的指向相应的函数。执行的函数会放入事件队列中在下一个时间片执行。需要指出的是这并不是要立即执行。函数一直会等到下一个时间片。这也就是上面结果的原因。Console.log(4)会在console.log(3)之前执行。 11.写一个函数判断一个字符串超过80个字符是否是回文结构正序和逆序想同。 答下面的函数如果str是回文则返回true否则返回false. function isPalindrome(str) { str str.replace(/\W/g, ).toLowerCase(); return (str str.split().reverse().join()); } 例如 console.log(isPalindrome(level)); // logs true console.log(isPalindrome(levels)); // logs false console.log(isPalindrome(A car, a man, a maraca)); // logs true 12.写一个sum函数使以下两种调用方式都正确。 console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5 答至少有两种方式实现 方法1 function sum(x) { if (arguments.length 2) { return arguments[0] arguments[1]; } else { return function(y) { return x y; }; } } 在JavaScript中函数可以通过arguments对象访问传入的给函数的参数。我们能通过在运行时访问length属性的值得到参数的个数。如果是两个参数我们直接相加并返回否则我们假定调用的是sum(2)(3),因此我们返回一个匿名函数通过sum()相加参数2并且把参数传给匿名函数参数3。 方法2 function sum(x, y) { if (y ! undefined) { return x y; } else { return function(y) { return x y; }; } } 在JavaScript中一个函数被调用是不需要输入参数完全匹配函数的参数定义的。如果输入参数超过函数定义的参数则超过的参数会被忽略另一方面如果输入的参数少于函数定义的参数则缺少的参数将会赋予undefined.因此上面的例子中通过判断第二个参数是否为undefined我们可以决定采用哪种函数调用和执行方式。 13.考虑一下以下的代码片段 for (var i 0; i 5; i) { var btn document.createElement(button); btn.appendChild(document.createTextNode(Button i)); btn.addEventListener(click, function(){ console.log(i); }); document.body.appendChild(btn); } a)当用户点击“Button4”的时候会打印什么并解释为什么 b)提供一个或多个正确的实现方式。 答a)无论点击哪个按钮都将打印5.因为任何按钮在调用onclick方法时for循环已经完成了变量i的值变成了5. (b).关键是要抓住在每一次循环for的时候要把i的值传人到最近创建的函数对象中下面有三个可能的方式解决这个问题 for (var i 0; i 5; i) { var btn document.createElement(button); btn.appendChild(document.createTextNode(Button i)); btn.addEventListener(click, (function(i) { return function() { console.log(i); }; })(i)); document.body.appendChild(btn); } 二种你可以将整个btn.addEventListener封装在一个新的匿名函数里。 for (var i 0; i 5; i) { var btn document.createElement(button); btn.appendChild(document.createTextNode(Button i)); (function (i) { btn.addEventListener(click, function() { console.log(i); }); })(i); document.body.appendChild(btn); } 三种可以将for循环换成array对象的本地调用方法forEach. [a, b, c, d, e].forEach(function (value, i) { var btn document.createElement(button); btn.appendChild(document.createTextNode(Button i)); btn.addEventListener(click, function() { console.log(i); }); document.body.appendChild(btn); }); 14.下面的代码将输出什么并解释原因 var arr1 john.split(); var arr2 arr1.reverse(); var arr3 jones.split(); arr2.push(arr3); console.log(array 1: length arr1.length last arr1.slice(-1)); console.log(array 2: length arr2.length last arr2.slice(-1)); 答输出结果如下 array 1: length5 lastj,o,n,e,s array 2: length5 lastj,o,n,e,s Arr1和arr2输出结果一样的原因如下: A.调用array对象的reverse()方法不仅仅返回转置后的数组它自身的顺序也转置了。 B.Reverse()方法返回的是指向array自身的一个引用因此arr2仅仅是arr1的一个引用无论对arr2怎么操作arr1也会受到影响arr1,arr2都指向同一个对象。 C.通过调用array的push()方法传人另一个array仅仅只是把传人的array作为一个元素添加到队列的尾部因此,arr2.push(arr3)是将arr3当作一个元素添加到arr2的队尾而不是像concat()方法一样合并两个array。 D.与Python类似JavaScript通过输入-1调用slice()是一种指向array队列尾部最后一个元素的方法。 15.下面代码的输出是什么并解释为什么 console.log(1 2 2); console.log(1 2 2); console.log(1 -1 2); console.log(1 1 2); console.log( A - B 2); console.log( A - B 2); 答上面代码的显示的结果是 122 32 02 112 NaN2 NaN 主要的问题是JavaScript是一种弱类型的语言它会在操作执行时自动转化数值类型。 例11”2””2”输出结果为”122”.第一个操作是1”2”,因为有个操作数是”2”是字符串JavaScript会在执行操作过程中转化成字符串的合并1转化成”1”1”2”得到结果为“12”然后“12”“2”结果为“122”。 例21 ”2””2”输出结果为“32”。第一个操作是”2”这被看成是一元操作因此JavaScript会把”2”的类型转为数字再赋予则为正整数2然后执行12得3但是当我们执行一个数字和字符串的操作3”2”时又将转化成字符串连接操作得到字符串“32”。 例31 -“1” “2”输出为“02”。这里首先定义操作优先级一元操作-高于因此”1”转为1赋予-转为-1加上1得结果0然后与最后的“2”转字符串连接结果为“02”。 例4“1” “1” “2”输出结果为112.首先执行一元操作得1然后与后面的“1”“2”执行字符串连接操作得结果“112”。 例5“a”-”b” ”2”输出结果为“NaN2”。因为字符串不存在-操作因此会将A,B转化成数字转化失败得到结果“NaN”再与“2”做字符串连接操作得到结果“NaN2”. 例6”a”-”b”2,输出结果为NaN因为字符串不存在-操作因此会将A,B转化成数字转化失败得到结果“NaN”再与2执行加操作但是NaN与任何数字操作结果还是NaN。 16.下面的代码如果队列太长会导致栈溢出怎样解决这个问题并且依然保持循环部分。 var list readHugeList(); var nextListItem function() { var item list.pop(); if (item) { // process the list item... nextListItem(); } }; 答为了避免栈溢出循环部分改为如下代码 var list readHugeList(); var nextListItem function() { var item list.pop(); if (item) { // process the list item... setTimeout( nextListItem, 0); } }; 栈溢出主要是因为循环事件而不是栈。当执行nextListItem时如果item不是null,在timeout函数中的nextListItem会推入到事件队列中。当事件空闲则会执行nextListItem,因此这种方法从开始到结束没有直接进行循环调用可以不用考虑循环次数。 17.什么是闭包并举例。 答闭包是一个内部函数访问外部定义的变量闭包有三种访问变量的方式。1在自身域的变量。2闭包函数域的变量。3全局变量。 例子 var globalVar xyz; (function outerFunc(outerArg) { var outerVar a; (function innerFunc(innerArg) { var innerVar b; console.log( outerArg outerArg \n innerArg innerArg \n outerVar outerVar \n innerVar innerVar \n globalVar globalVar); })(456); })(123); 上面例子中在innerFunc中访问的变量分别在innerFunc,outFunc和全局命名空间里。输出结果如下 outerArg 123 innerArg 456 outerVar a innerVar b globalVar xyz 18.下面代码的输出结果是什么并解释原因 for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, i * 1000 ); } 答例子显示的结果不是预想的0123和4.而是5555和5.原因是每个执行的函数在循环完全执行完成后i最后的赋值是5.闭包的方式可以解决这个问题在每个循环中为次的循环变量创建一个唯一域如下 for (var i 0; i 5; i) { (function(x) { setTimeout(function() { console.log(x); }, x * 1000 ); })(i); } 则结果将会是01234. 19.下面代码的输出结果是什么并解释原因。 console.log(0 || 1 (0 || 1)); console.log(1 || 2 (1 || 2)); console.log(0 1 (0 1)); console.log(1 2 (1 2)); 答代码段的输出结果如下 0 || 1 1 1 || 2 1 0 1 0 1 2 2 在JavaScript中||和是逻辑操作将从左往右进行逻辑判断。||操作符的表达式是X|YX先进行评估判断一个boolean逻辑值如果为true则值为X。如果为false则值为Y。操作恰恰相反。 20.下面代码的执行结果是什么并解释原因 console.log(false 0) console.log(false 0) 答代码的执行结果为true false; 在JavaScript中有两个等于操作其中三等号更像传统的等于操作如果表达是两边的类型和值都相等才为true双等号会在比较相等时进行强制的值比较因此更好的编程风格是采用同样的应采用!而不是!。 21.下面代码的输出结果是什么并解释原因。 var a{}, b{key:b}, c{key:c}; a[b]123; a[c]456; console.log(a[b]); 答输出的结果应该是456而不是123. 原因是当我们设置一个object属性时JavaScript会隐形的将参数值字符串化。在这个例子中b和c都是objects他们会转化为”[object,object]”结果a[b]和a[c]都等于a[”[object,object]”],因此设置或者引用a[c]等同于设置和引用a[b]. 22.给出以下代码的输出结果并解释原因 console.log((function f(n){return ((n 1) ? n * f(n-1) : n)})(10)); 答代码块的输出结果是10facorial值也就是(10或者 3628800,f()会循环调用自身直到调用f(1),返回1因此以下是执行过程。 f(1): returns n, which is 1 f(2): returns 2 * f(1), which is 2 f(3): returns 3 * f(2), which is 6 f(4): returns 4 * f(3), which is 24 f(5): returns 5 * f(4), which is 120 f(6): returns 6 * f(5), which is 720 f(7): returns 7 * f(6), which is 5040 f(8): returns 8 * f(7), which is 40320 f(9): returns 9 * f(8), which is 362880 f(10): returns 10 * f(9), which is 3628800 23.下面代码块的输出是什么并解释原因。 (function(x) { return (function(y) { console.log(x); })(2) })(1); 答输出结果是1尽管x值在内部函数里没有设置。 在JavaScript中闭包是作为内部函数实现的也就是一个函数定义在另一个函数内部闭包的重要特性是内部函数能够访问外部函数的变量。在这个例子中尽管x没有在内部函数定义在外部函数里找到了定义的值为1的x变量。 24.下面代码的输出结果是什么并解释原因如何修改。 var hero { _name: John Doe, getSecretIdentity: function (){ return this._name; } }; var stoleSecretIdentity hero.getSecretIdentity; console.log(stoleSecretIdentity()); console.log(hero.getSecretIdentity()); 答输出结果为 undefined JohnDoe。 第一个为undefined是因为我们直接从hero对象中提取stoleSecretIdentity()stoleSecretIdentity()是从全局上下文里调用的window对象不存在_name属性。可以采用下面的方式正确实现预期。 var stoleSecretIdentity hero.getSecretIdentity.bind(hero); 25.创建一个函数赋予page的一个dom元素将访问自身和它所有的子元素不仅仅是直接子元素。因为每个元素都要访问到需要传人一个回掉函数。函数的参数如下一个Dom元素一个回调函数。 答可以采用深度优先算法。如下 function Traverse(p_element,p_callback) { p_callback(p_element); var list p_element.children; for (var i 0; i list.length; i) { Traverse(list[i],p_callback); // recursive call } }