日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
帶你填一些JS容易出錯(cuò)的坑

前言

題目主要來自看到過的易錯(cuò)題,還有經(jīng)典的44道 JavaScript Puzzlers!, stackoverflow 這上面有很多Questions不錯(cuò)的,可以好好補(bǔ)一補(bǔ)基礎(chǔ)。

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的建平網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

. VS = 操作符優(yōu)先級

 
 
 
 
  1. let a = {n : 1};
  2.       let b = a;
  3.       a.x = a = {n: 2};
  4.       
  5.       console.log(a.x)
  6.       console.log(b.x)

輸出是什么呢?

真的想明白了嗎?

 
 
 
 
  1. undefined
  2. { n : 2}

你真的了解作用域嗎

 
 
 
 
  1. var a = 0,  
  2.           b = 0;
  3.       function A(a) {
  4.           A = function (b) {
  5.               console.log(a + b++)
  6.           }
  7.           console.log(a++)
  8.       }
  9.       A(1)
  10.       A(2)

留給你們思考,我可是第一遍就做錯(cuò)了(;′⌒`)

答案 1 4

可以好好想一想,你會(huì)茅塞頓開的。

類數(shù)組的length

 
 
 
 
  1. var obj = {
  2.           "2" : 3,
  3.           "3" : 4,
  4.           "length" : 2,
  5.           "splice" : Array.prototype.splice,
  6.           "push" : Array.prototype.push
  7.       }
  8.       obj.push(1)
  9.       obj.push(2)
  10.       console.log(obj)

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:Object(4) [empty × 2, 1, 2, splice: ?, push: ?]

 
 
 
 
  1. 解釋就是第一次使用push,obj對象的push方法設(shè)置obj[2] = 1,obj.length++
  2. 解釋就是第一次使用push,obj對象的push方法設(shè)置obj[3] = 2,obj.length++
  3. 使用console.log()方法輸出的時(shí)候,因?yàn)閛bj上有l(wèi)ength屬性和splice方法,故將其作為數(shù)組輸出打印
  4. 打印時(shí)因?yàn)閿?shù)組未設(shè)置下標(biāo)為0和1的值,故打印的結(jié)果就是empty,主動(dòng)獲取obj[0] = undefined

非匿名自執(zhí)行函數(shù),函數(shù)名只讀

 
 
 
 
  1. var b = 10;
  2.       (function b(){
  3.           // 'use strict'
  4.           b = 20
  5.           console.log(b)
  6.       })()

輸出的結(jié)果是什么?

 
 
 
 
  1. Function b
 
 
 
 
  1. - 如標(biāo)題一樣,非匿名自執(zhí)行函數(shù),函數(shù)名不可以修改,嚴(yán)格模式下會(huì)TypeError,
  2. - 非嚴(yán)格模式下,不報(bào)錯(cuò),修改也沒有用。
  3. - 查找變量b時(shí),立即執(zhí)行函數(shù)會(huì)有內(nèi)部作用域,會(huì)先去查找是否有b變量的聲明,有的話,直接復(fù)制
  4. - 確實(shí)發(fā)現(xiàn)具名函數(shù)Function b(){} 所以就拿來做b的值
  5. - IIFE的函數(shù)內(nèi)部無法進(jìn)行復(fù)制(類似于const)

非匿名自執(zhí)行函數(shù) II

 
 
 
 
  1. var b = 10;
  2.       (function b(){
  3.           // 'use strict'
  4.           var b = 20
  5.           console.log(window.b) 
  6.           console.log(b)
  7.       })()

輸出是多少呢?

 
 
 
 
  1. 10
  2. 20
  3. // 訪問b變量的時(shí)候,發(fā)現(xiàn)var b = 20;在當(dāng)前作用域中找到了b變量,于是把b的值作為20

非匿名自執(zhí)行函數(shù) III

 
 
 
 
  1. var b = 10;
  2.       (function b(){
  3.           console.log(b)
  4.           b = 5
  5.           console.log(window.b)
  6.           var b = 20
  7.           console.log(b)
  8.       })()

輸出的結(jié)果是多少呢?

這個(gè)問題應(yīng)該不難,就留給你們思考吧

變量提升

 
 
 
 
  1. var name = 'World!';
  2. (function () {
  3.     if (typeof name === 'undefined') {
  4.         var name = 'Jack';
  5.         console.log('Goodbye ' + name);
  6.     } else {
  7.         console.log('Hello ' + name);
  8.     }
  9. })();

在 JavaScript中, Fun 和 var 會(huì)被提升

相當(dāng)于

 
 
 
 
  1. var name = 'World!';
  2. (function () {
  3.     var name;
  4.     if (typeof name === 'undefined') {
  5.         name = 'Jack';
  6.         console.log('Goodbye ' + name);
  7.     } else {
  8.         console.log('Hello ' + name);
  9.     }
  10. })();

鞏固一下:

 
 
 
 
  1. var str = 'World!';   
  2.    (function (name) {
  3.    if (typeof name === 'undefined') {
  4.        var name = 'Jack';
  5.        console.log('Goodbye ' + name);
  6.    } else {
  7.        console.log('Hello ' + name);
  8.    }
  9.    })(str);
  10.    答案:Hello World 因?yàn)閚ame已經(jīng)變成函數(shù)內(nèi)局部變量

最大整數(shù)

 
 
 
 
  1. var END = Math.pow(2, 53);
  2. var START = END - 100;
  3. var count = 0;
  4. for (var i = START; i <= END; i++) {
  5.     count++;
  6. }
  7. console.log(count);

一個(gè)知識點(diǎn):Infinity

 
 
 
 
  1. 在 JS 里, Math.pow(2, 53) == 9007199254740992 是可以表示的最大值. 最大值加一還是最大值. 所以循環(huán)不會(huì)停.

稀疏數(shù)組與密數(shù)組

 
 
 
 
  1. var ary = [0,1,2];
  2. ary[10] = 10;
  3. ary.filter(function(x) { return x === undefined;});

 執(zhí)行結(jié)果如何呢?

做這個(gè)題目,你需要了解稀疏數(shù)組和密集數(shù)組

  • 譯 JavaScript中的稀疏數(shù)組與密集數(shù)組
  • Array/filter

看過源碼的同學(xué)應(yīng)該知道,filter源碼中,會(huì)去判斷數(shù)組的這個(gè)索引值是不是數(shù)組的一個(gè)屬性,有興趣的同學(xué)可以看看我寫的這篇關(guān)于數(shù)組的:[干貨]從詳細(xì)操作js數(shù)組到淺析v8中array.js

 
 
 
 
  1. 0 in ary; => true
  2. 3 in ary; => false
  3. 10 in ary; => true
  4. 也就是說 從 3 - 9 都是沒有初始化的'坑'!, 這些索引并不存在與數(shù)組中. 在 array 的函數(shù)調(diào)用的時(shí)候是會(huì)跳過這些'坑'的.

所以答案就是[]

浮點(diǎn)運(yùn)算

 
 
 
 
  1. var two   = 0.2
  2. var one   = 0.1
  3. var eight = 0.8
  4. var six   = 0.6
  5. [two - one == one, eight - six == two]

你認(rèn)為結(jié)果是多少呢?面試遇到這個(gè)問題,應(yīng)該怎么回答呢?

 
 
 
 
  1. [true,false]

可以看看這些文章:

  • 探尋 JavaScript 精度問題以及解決方案
  • 從0.1+0.2=0.30000000000000004再看JS中的Number類型

Switch

 
 
 
 
  1. function showCase(value) {
  2.     switch(value) {
  3.     case 'A':
  4.         console.log('Case A');
  5.         break;
  6.     case 'B':
  7.         console.log('Case B');
  8.         break;
  9.     case undefined:
  10.         console.log('undefined');
  11.         break;
  12.     default:
  13.         console.log('Do not know!');
  14.     }
  15. }
  16. showCase(new String('A'));

運(yùn)行結(jié)果如何呢?

 
 
 
 
  1. switch 是嚴(yán)格比較, String 實(shí)例和 字符串不一樣.
  2. 答案自然是'Do not know' 
  3. 所以一般情況下,寫switch語句,也建議寫default

String("A")

 
 
 
 
  1. function showCase2(value) {
  2.     switch(value) {
  3.     case 'A':
  4.         console.log('Case A');
  5.         break;
  6.     case 'B':
  7.         console.log('Case B');
  8.         break;
  9.     case undefined:
  10.         console.log('undefined');
  11.         break;
  12.     default:
  13.         console.log('Do not know!');
  14.     }
  15. }
  16. showCase2(String('A'));

運(yùn)行結(jié)果呢?

 
 
 
 
  1. 答案:Case A
  2. 解析:String('A')就是返回一個(gè)字符串

%運(yùn)算符

 
 
 
 
  1. function isOdd(num) {
  2.     return num % 2 == 1;
  3. }
  4. function isEven(num) {
  5.     return num % 2 == 0;
  6. }
  7. function isSane(num) {
  8.     return isEven(num) || isOdd(num);
  9. }
  10. var values = [7, 4, '13', -9, Infinity];
  11. values.map(isSane);

運(yùn)行的結(jié)果如何呢?

 
 
 
 
  1. 答案:[true, true, true, false, false]
  2. 解析:%如果不是數(shù)值會(huì)調(diào)用Number()去轉(zhuǎn)化
  3.      '13' % 2       // 1
  4.       Infinity % 2  //NaN  Infinity 是無窮大
  5.       -9 % 2        // -1
  6. 鞏固:9 % -2        // 1   余數(shù)的正負(fù)號隨第一個(gè)操作數(shù)

數(shù)組的原型是什么

 
 
 
 
  1. Array.isArray( Array.prototype )

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:true
  2. 解析:Array.prototype是一個(gè)數(shù)組
  3. 數(shù)組的原型是數(shù)組,對象的原型是對象,函數(shù)的原型是函數(shù)

寬松相等 ==

 
 
 
 
  1. []==[]

答案是什么呢

 
 
 
 
  1. 答案:false
  2. 解析:兩個(gè)引用類型, ==比較的是引用地址

== 和 !優(yōu)先級

 
 
 
 
  1. []== ![] 

結(jié)果是什么呢?

 
 
 
 
  1. (1)! 的優(yōu)先級高于== ,右邊Boolean([])是true,取返等于 false
  2. (2)一個(gè)引用類型和一個(gè)值去比較 把引用類型轉(zhuǎn)化成值類型,左邊0
  3. (3)所以 0 == false  答案是true

數(shù)字與字符串相加減

 
 
 
 
  1. '5' + 3
  2. '5' - 3

結(jié)果是多少呢?

 
 
 
 
  1. 答案:53  2
  2. 解析:加號有拼接功能,減號就是邏輯運(yùn)算
  3. 鞏固:typeof (+"1")   // "number" 對非數(shù)值+—常被用來做類型轉(zhuǎn)換相當(dāng)于Number()

一波騷操作 + - + + + - +

 
 
 
 
  1. 1 + - + + + - + 1

結(jié)果是多少呢

 
 
 
 
  1. 答案:2
  2. 解析:+-又是一元加和減操作符號,就是數(shù)學(xué)里的正負(fù)號。負(fù)負(fù)得正哈。 
  3. 鞏固: 一元運(yùn)算符還有一個(gè)常用的用法就是將自執(zhí)行函數(shù)的function從函數(shù)聲明變成表達(dá)式。
  4.       常用的有 + - ~ !void
  5.       + function () { }
  6.       - function () { }
  7.       ~ function () { }
  8.       void function () { }

又是稀疏數(shù)組?Array.prototype.map()

 
 
 
 
  1. var ary = Array(3);
  2. ary[0]=2
  3. ary.map(function(elem) { return '1'; });

輸出結(jié)果是多少呢?

 
 
 
 
  1. 稀疏數(shù)組
  2. 題目中的數(shù)組其實(shí)是一個(gè)長度為3, 但是沒有內(nèi)容的數(shù)組, array 上的操作會(huì)跳過這些未初始化的'坑'.
  3. 所以答案是 ["1", empty × 2]

這里貼上 Array.prototype.map 的 polyfill.

 
 
 
 
  1. Array.prototype.map = function(callback, thisArg) {
  2.         var T, A, k;
  3.         if (this == null) {
  4.             throw new TypeError(' this is null or not defined');
  5.         }
  6.         var O = Object(this);
  7.         var len = O.length >>> 0;
  8.         if (typeof callback !== 'function') {
  9.             throw new TypeError(callback + ' is not a function');
  10.         }
  11.         if (arguments.length > 1) {
  12.             T = thisArg;
  13.         }
  14.         A = new Array(len);
  15.         k = 0;
  16.         while (k < len) {
  17.             var kValue, mappedValue;
  18.             if (k in O) {
  19.                 kValue = O[k];
  20.                 mappedValue = callback.call(T, kValue, k, O);
  21.                 A[k] = mappedValue;
  22.             }
  23.             k++;
  24.         }
  25.         return A;
  26.     };

JS是如何存儲(chǔ)

 
 
 
 
  1. var a = 111111111111111110000,
  2. b = 1111;
  3. a + b;

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:11111111111111111000
  2. 解析:在JavaScript中number類型在JavaScript中以64位(8byte)來存儲(chǔ)。
  3. 這64位中有符號位1位、指數(shù)位11位、實(shí)數(shù)位52位。
  4. 2的53次方時(shí),是最大值。
  5. 其值為:9007199254740992(0x20000000000000)。
  6. 超過這個(gè)值的話,運(yùn)算的結(jié)果就會(huì)不對.

數(shù)組比較大小

 
 
 
 
  1. var a = [1, 2, 3],
  2.     b = [1, 2, 3],
  3.     c = [1, 2, 4]
  4. a ==  b
  5. a === b
  6. a >   c
  7. a <   c

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:false, false, false, true
  2. 解析:相等(==)和全等(===)還是比較引用地址
  3.      引用類型間比較大小是按照字典序比較,就是先比第一項(xiàng)誰大,相同再去比第二項(xiàng)。

三元運(yùn)算符優(yōu)先級

 
 
 
 
  1. var val = 'smtg';
  2. console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:Something
  2. 解析:字符串連接比三元運(yùn)算有更高的優(yōu)先級 
  3.      所以原題等價(jià)于 'Value is true' ? 'Somthing' : 'Nonthing' 
  4.      而不是 'Value   is' + (true ? 'Something' : 'Nonthing')
  5. 鞏固:
  6.     1 || fn() && fn()   //1  
  7.     1 || 1 ? 2 : 3 ;    //2  

原型

 
 
 
 
  1. var a = {}, b = Object.prototype;
  2. [a.prototype === b, Object.getPrototypeOf(a) === b] 

執(zhí)行結(jié)果是多少呢

 
 
 
 
  1. 答案:false, true
  2. 解析:Object 的實(shí)例是 a,a上并沒有prototype屬性
  3.      a的__poroto__ 指向的是Object.prototype,也就是Object.getPrototypeOf(a)。a的原型對象是b

原型II

 
 
 
 
  1. function f() {}
  2. var a = f.prototype, b = Object.getPrototypeOf(f);
  3. a === b         

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:false
  2. 解析:a是構(gòu)造函數(shù)f的原型 : {constructor: ?}
  3. b是實(shí)例f的原型對象 : ? () { [native code] }

函數(shù)名稱

 
 
 
 
  1. function foo() { }
  2. var oldName = foo.name;
  3. foo.name = "bar";
  4. [oldName, foo.name]     

代碼執(zhí)行結(jié)果是什么?

 
 
 
 
  1. 答案:["foo", "foo"]
  2. 解析:函數(shù)的名字不可變.

[typeof null, null instanceof Object]

 
 
 
 
  1. 答案:["object", false]
  2. 解析:null代表空對象指針,所以typeof判斷成一個(gè)對象??梢哉fJS設(shè)計(jì)上的一個(gè)BUG
  3.      instanceof 實(shí)際上判斷的是對象上構(gòu)造函數(shù),null是空當(dāng)然不可能有構(gòu)造函數(shù)
  4. 鞏固:null == undefined //true    null === undefined //flase

[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]

 
 
 
 
  1. 答案:Error
  2. 解析:Math.pow (x , y)  x 的 y 次冪的值
  3.      reduce(fn,total)
  4.      fn (total, currentValue, currentIndex, arr) 
  5.          如果一個(gè)函數(shù)不傳初始值,數(shù)組第一個(gè)組默認(rèn)為初始值.
  6.          [3,2,1].reduce(Math.pow)
  7.          Math.pow(3,2) //9
  8.          Math.pow(9,1) //9
  9. 鞏固題,可以做一做:
  10.   [].reduce(Math.pow)       //空數(shù)組會(huì)報(bào)TypeError
  11.      [1].reduce(Math.pow)      //只有初始值就不會(huì)執(zhí)行回調(diào)函數(shù),直接返回1
  12.      [].reduce(Math.pow,1)     //只有初始值就不會(huì)執(zhí)行回調(diào)函數(shù),直接返回1
  13.      [2].reduce(Math.pow,3)    //傳入初始值,執(zhí)行回調(diào)函數(shù),返回9

replace

 
 
 
 
  1. "1 2 3".replace(/\d/g, parseInt)

輸出是什么呢?

 
 
 
 
  1. 答案:"1 NaN 3"
  2. 解析:replace() 回調(diào)函數(shù)的四個(gè)參數(shù):
  3.       1、匹配項(xiàng)  
  4.       2、與模式中的子表達(dá)式匹配的字符串  
  5.       3、出現(xiàn)的位置  
  6.       4、stringObject 本身 。
  7. 如果沒有與子表達(dá)式匹配的項(xiàng),第二參數(shù)為出現(xiàn)的位置.所以第一個(gè)參數(shù)是匹配項(xiàng),第二個(gè)參數(shù)是位置
  8.  parseInt('1', 0)
  9.  parseInt('2', 2)  //2進(jìn)制中不可能有2
  10.  parseInt('3', 4)

eval用法

 
 
 
 
  1. function f() {}
  2. var parent = Object.getPrototypeOf(f);
  3. f.name // ?
  4. parent.name // ?
  5. typeof eval(f.name) // ?
  6. typeof eval(parent.name) //  ?  

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:"f", "Empty", "function", error
  2. 解析:f的函數(shù)名就是f
  3.      parent是f原型對象的名字為"" ,
  4.      先計(jì)算eval(f.name) 為 f,f的數(shù)據(jù)類型是function
  5.      eval(parent.name) 為undefined, "undefined"

new Date()

 
 
 
 
  1. var a = new Date("2014-03-19"),
  2. b = new Date(2014, 03, 19);
  3. [a.getDay() === b.getDay(), a.getMonth() === b.getMonth()]

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:[false, false]
  2. 解析:var a = new Date("2014-03-19")    //能夠識別這樣的字符串,返回想要的日期
  3.       Wed Mar 19 2014 08:00:00 GMT+0800 (CST)
  4.       b = new Date(2014, 03, 19);       //參數(shù)要按照索引來
  5.       Sat Apr 19 2014 00:00:00 GMT+0800 (CST)
  6.       月是從0索引,日期是從1 
  7.       getDay()是獲取星期幾
  8.       getMonth()是獲取月份所以都不同
  9. 鞏固: [a.getDate() === b.getDate()] //true

new Date() II

 
 
 
 
  1. var a = Date(0);
  2. var b = new Date(0);
  3. var c = new Date();
  4. [a === b, b === c, a === c]

這段代碼的執(zhí)行結(jié)果?

 
 
 
 
  1. 答案:[false, false, false]
  2. 解析:當(dāng)日期被作為構(gòu)造函數(shù)調(diào)用時(shí),它返回一個(gè)相對于劃時(shí)代的對象(JAN 01 1970)。
  3. 當(dāng)參數(shù)丟失時(shí),它返回當(dāng)前日期。當(dāng)它作為函數(shù)調(diào)用時(shí),它返回當(dāng)前時(shí)間的字符串表示形式。
  4. a是字符串   a === b // 數(shù)據(jù)類型都不同,肯定是false
  5. b是對象     b === c // 引用類型,比的是引用地址
  6. c也是對象   a === c // 數(shù)據(jù)類型都不同,肯定是false

new Date() III

 
 
 
 
  1. var a = new Date("epoch")

你認(rèn)為結(jié)果是多少呢?

 
 
 
 
  1. 答案:Invalid Date {}
  2. 解析:您得到“無效日期”,這是一個(gè)實(shí)際的日期對象(一個(gè)日期的日期為true)。但無效。這是因?yàn)闀r(shí)間內(nèi)部保持為一個(gè)數(shù)字,在這種情況下,它是NA。
  3.       在chrome上是undefined 
  4.       正確的是格式是var d = new Date(year, month, day, hours, minutes, seconds, milliseconds);

Function.length

 
 
 
 
  1. var a = Function.length,
  2. b = new Function().length
  3. a === b

這段代碼的執(zhí)行結(jié)果是?

 
 
 
 
  1. 答案:false
  2. 解析:首先new在函數(shù)帶()時(shí)運(yùn)算優(yōu)先級和.一樣所以從左向右執(zhí)行
  3.      new Function() 的函數(shù)長度為0
  4. 鞏固:function fn () {
  5.          var a = 1;
  6.       }
  7.       console.log(fn.length) 
  8.       //0 fn和new Function()一樣
  • 要是看過往期的這篇文章[誠意滿滿]帶你填一些JS容易出錯(cuò)的坑 就可以給我點(diǎn)個(gè)贊關(guān)注一下啦,下面的內(nèi)容都是這篇文章的內(nèi)容。

[1,2,5,10].sort()

不寫回調(diào)函數(shù)的話,是按照什么排序呢?

JavaScript默認(rèn)使用字典序(alphanumeric)來排序。因此結(jié)果是[1,10,2,5]

正確排序的話,應(yīng)該[1,2,5,10].sort( (a,b) => a-b )

"b" + "a" + +"a" + "a"

你認(rèn)為輸出是什么?

上面的表達(dá)式相當(dāng)于'b'+'a'+ (+'a')+'a',因?yàn)?+'a')是NaN,所以:

'b'+'a'+ (+'a')+'a' = 'b'+'a'+ "NaN"+'a'='baNaNa'

閉包

這是一個(gè)經(jīng)典JavaScript面試題

 
 
 
 
  1. let res = new Array()
  2.        for(var i = 0; i < 10; i++){
  3.            res.push(function(){
  4.                return console.log(i)
  5.            })
  6.        }
  7.        res[0]() 
  8.        res[1]()
  9.        res[2]()

期望輸出的是0,1,2,實(shí)際上卻不會(huì)。原因就是涉及作用域,怎么解決呢?

  • [x] 使用let代替var,形成塊級作用域
  • [x] 使用bind函數(shù)。
 
 
 
 
  1. res.push(console.log.bind(null, i))

解法還有其他的,比如使用IIFE,形成私有作用域等等做法。

又一經(jīng)典閉包問題

 
 
 
 
  1. function fun(n,o) {
  2.   console.log(o)
  3.   return {
  4.     fun:function(m){
  5.       return fun(m,n);
  6.     }
  7.   };
  8. }
  9. var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
  10. var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
  11. var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?

留給你們思考

隱式轉(zhuǎn)換

 
 
 
 
  1. var a = [0];
  2. if (a) {
  3.   console.log(a == true);
  4. } else {
  5.   console.log("wut");
  6. }

你們覺得答案是多少呢?這題涉及到隱式轉(zhuǎn)換了,這個(gè)坑我自己的好好補(bǔ)一補(bǔ)

// 答案:false

再來一道?

 
 
 
 
  1. function fn() {
  2.     return 20;
  3. }
  4. console.log(fn + 10); // 輸出結(jié)果是多少
 
 
 
 
  1. function fn() {
  2.     return 20;
  3. }
  4. fn.toString = function() {
  5.     return 10;
  6. }
  7. console.log(fn + 10);  // 輸出結(jié)果是多少?
 
 
 
 
  1. function fn() {
  2.     return 20;
  3. }
  4. fn.toString = function() {
  5.     return 10;
  6. }
  7. fn.valueOf = function() {
  8.     return 5;
  9. }
  10. console.log(fn + 10); // 輸出結(jié)果是多少?

說到底JS類型轉(zhuǎn)換的好好補(bǔ)一補(bǔ)了

你真的理解操作符嗎

 
 
 
 
  1. [1<2<3,3<2<1]
  2. //[false,false]
  3. //[true,true]
  4. //[false,true]
  5. //[true,false]

選一個(gè)吧,比較操作符,賦值運(yùn)算符優(yōu)先級哪個(gè)更高呢?

0.1+0.2 !== 0.3 ?

面試的時(shí)候,問你這個(gè)問題,要是回答錯(cuò)誤的話,估計(jì)面試官對基礎(chǔ)很是懷疑!!!

問你這個(gè)題目的時(shí)候,你可以牽扯出很多問題,比如JS如何存儲(chǔ)小數(shù)的呢?比如聊一聊二進(jìn)制,比如實(shí)際開發(fā)中,遇到精度的問題,你是怎么解決的,你有什么好辦法。

聊完這個(gè),你可以牽扯出最大安全數(shù),比如JavaScript的最大安全整數(shù)是多少,超出這個(gè)范圍的話,怎么解決精度問題呢?

ES規(guī)范中新提出的BigInt解決了什么問題呢,你又發(fā)現(xiàn)了BigInt中哪些坑呢?

如何解決精度問題呢?

這里推薦Number-Precision庫,不到1K的體積。

arguments

 
 
 
 
  1. function sidEffecting(ary) {
  2.           ary[0] = ary[2];
  3.       }
  4.       function bar(a, b, c) {
  5.           c = 10
  6.           sidEffecting(arguments);
  7.           return a + b + c;
  8.       }
  9.       function demo (arg) {
  10.           arg.name = 'new Name'
  11.       }
  12.       console.log(bar(2, 2, 2))

涉及到ES6語法,這題答案肯定都會(huì)做是22,但是呢,稍微改變一下題目,就比較坑了….

 
 
 
 
  1. function sidEffecting(ary) {
  2.           ary[0] = ary[2];
  3.       }
  4.       function bar(a, b, c = 4) {
  5.           c = 10
  6.           sidEffecting(arguments);
  7.           return a + b + c;
  8.       }
  9.       function demo (arg) {
  10.           arg.name = 'new Name'
  11.       }
  12.       console.log(bar(2, 2, 2))

這個(gè)答案是多少呢?根據(jù)MDN上對argument有更加準(zhǔn)確的定義,看argument

  • 當(dāng)非嚴(yán)格模式中的函數(shù)有包含剩余參數(shù)、默認(rèn)參數(shù)和解構(gòu)賦值,那么arguments對象中的值不會(huì)跟蹤參數(shù)的值(反之亦然)。

找到這句話,bar函數(shù)存在默認(rèn)參數(shù),并且在非嚴(yán)格模式下,所以不會(huì)跟蹤參數(shù)的值,自然結(jié)果就14

請讀者細(xì)細(xì)體會(huì)

瀏覽器

 
 
 
 
  1. let demo1 = {class: "Animal", name: 'sheet'};
  2.       console.log(demo1.class)

比較流氓,這個(gè)跟瀏覽器相關(guān),class是保留字(現(xiàn)在的話,class是關(guān)鍵字),答案并不要緊,重要的是自己在取屬性名稱的時(shí)候盡量避免保留字. 如果使用的話請加引號 a['class']。

保留字vs關(guān)鍵字

個(gè)人理解的話,關(guān)鍵字就是有特殊含義的,不用用作變量名。比如

 
 
 
 
  1. let class = 123;

現(xiàn)在看來肯定報(bào)錯(cuò),那有什么需要我們注意的呢?

 
 
 
 
  1. let undefined = 123;

這樣子并不會(huì)報(bào)錯(cuò),這個(gè)跟瀏覽器有點(diǎn)關(guān)系,這樣子看來undefined不是關(guān)鍵字。所以為了保險(xiǎn)起見,建議大家在判斷一個(gè)變量是不是未定義的話,盡量使用void 0 === undefined 很有可能undefined會(huì)被當(dāng)作是變量來賦值

void 0 值就是undefined

["1", "2", "3"].map(parseInt)

這個(gè)應(yīng)該是經(jīng)常遇見的題了,搞明白很簡單,map函數(shù)怎么使用,parseInt函數(shù)怎么使用

關(guān)于Array數(shù)組的話,我之前寫了一篇文章,從源碼角度解析大部分方法

點(diǎn)進(jìn)去重溫一遍:[干貨]從詳細(xì)操作js數(shù)組到淺析v8中array.js

map接受兩個(gè)參數(shù),一個(gè)callback,一個(gè)this,即調(diào)用函數(shù)時(shí)this指向,其中callback回調(diào)函數(shù)是三個(gè)參數(shù),一個(gè)currentValue,index,array;

parseInt接受兩個(gè)參數(shù):string,radix(基數(shù))

返回NaN有兩種情況

  • radix 小于 2 或大于 36 ,或
  • 第一個(gè)非空格字符不能轉(zhuǎn)換為數(shù)字。
  • 當(dāng)radix是0或者undefined時(shí),又是特殊情況,具體異步MDN
 
 
 
 
  1. parseInt('1', 0);
  2. parseInt('2', 1);
  3. parseInt('3', 2);

兩者結(jié)合的話,結(jié)果自然很明顯,[1,NaN,NaN]

Math.min() 為什么比 Math.max() 大?

 
 
 
 
  1. Math.min() < Math.max() // false

按照常規(guī)思路的話,應(yīng)該是true,畢竟最小值應(yīng)該小于最大值,但是實(shí)際情況是false

原因:

  • Math.min 的參數(shù)是 0 個(gè)或者多個(gè)。如果是多個(gè)參數(shù)很容易理解,返回參數(shù)中最小的。
  • 如果是0個(gè)參數(shù),或者沒有參數(shù),則返回 Infinity。
  • 而 Math.max() 沒有傳遞參數(shù)時(shí)返回的是 -Infinity。

要是面試官問這個(gè)問題,額。。。。

[].concat[1,2,3]

輸出是什么?注意不是[].concat([1,2,3])

 
 
 
 
  1. // [1,2,3]
  2. // Uncaught SyntaxError: ....
  3. // undefined

答案是undefined,原因是什么呢?

第一步計(jì)算[].concat,結(jié)果是Array.prototype.concat

第二步執(zhí)行一個(gè)逗號操作符,逗號操作符對它的每個(gè)操作對象求值(從左至右),然后返回最后一個(gè)操作對象的值。

 
 
 
 
  1. >1,2,3
  2. 返回3

第三步執(zhí)行一個(gè)數(shù)組訪問運(yùn)算或?qū)傩栽L問運(yùn)算

所以上面[].concat[1,2,3] 等價(jià)于Array.prototype.concat[3]

那么結(jié)果自然就是 undefined。

[1,2,NaN,3].indexOf(NaN)

//2 or -1

indexOf方法會(huì)進(jìn)行嚴(yán)格相等判斷

NaN !== NaN

怎么辦呢?

 
 
 
 
  1. let realIsNaN = value => typeof value === 'number' && isNaN(value);

先要判斷類型,是因?yàn)樽址D(zhuǎn)換會(huì)先轉(zhuǎn)換成數(shù)字,轉(zhuǎn)換失敗為 NaN。所以和 NaN 相等。

 
 
 
 
  1. isNaN('jjjj') —> true

第二種方法

 
 
 
 
  1. let realIsNaN = value => value !== value;

Number.isFinite & isFinite

 
 
 
 
  1. Number.isFinite('0') === isFinite('0')
  2. Number.isFinite(0) === isFinite('0')

打印結(jié)果是什么,能不能具體說一說?

Number.isFinite()檢測有窮性的值,唯一和全局isFinite()函數(shù)相比,這個(gè)方法不會(huì)強(qiáng)制將一個(gè)非數(shù)值的參數(shù)轉(zhuǎn)換成數(shù)值,這就意味著,只有數(shù)值類型的值,且是有窮的(finite),才返回 true。

自然答案就是 false,true

一道容易被人輕視的面試題

 
 
 
 
  1. function&
    本文名稱:帶你填一些JS容易出錯(cuò)的坑
    URL分享:http://www.5511xx.com/article/coohcjp.html