javascript
试试看 ? 离奇古怪的javascript题目
來源地址:
http://dmitrysoshnikov.com/ecmascript/the-quiz/#q1
?
另一篇帖子 看看國外的javascript題目,你能全部做對嗎?
http://www.cnblogs.com/aaronjs/p/3172112.html
答案都是自己總結(jié)的,畢竟是人肉解釋器,解釋不一定完全正確,如有不對歡迎大家指出!
?
題目1. 結(jié)果是什么?
typeof typeof(null)- “undefined”
- SyntaxError
- “string”
- “object”
- TypeError
?
題目2. 下面的檢測是否等價(jià)?
typeof foo == 'undefined' typeof foo === 'undefined'- Yes
- No
?
題目3. 結(jié)果是什么?
100['toString']['length']- 100
- 3
- 1
- 8
- 0
- SyntaxError
這個估計(jì)好多人想不通了
JavaScript 中所有變量都是對象,除了兩個例外 null 和 undefined
false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} Foo.bar = 1; Foo.bar; // 1一個常見的誤解是數(shù)字的字面值(literal)不是對象。這是因?yàn)?JavaScript 解析器的一個錯誤, 它試圖將點(diǎn)操作符解析為浮點(diǎn)數(shù)字面值的一部分。
2.toString(); // 出錯:SyntaxError例如以下這種就OK
true.toString() "true"false.toString() "false"01.toString() "1"0x20.toString() "32"true.toString()、false.toString()、02.toString()、 0x20.toString()都是可以的
我仔細(xì)查了下,網(wǎng)上大多給的解釋
2.toString()出錯是因?yàn)榻忉屍髯x到“2. ”不知道這個“點(diǎn)”究竟該作為小數(shù)點(diǎn)還是“.”操作符, 或者也就是說在這里產(chǎn)生了一個“shift-shift conflit”
有很多變通方法可以讓數(shù)字的字面值看起來像對象
2..toString(); // 第二個點(diǎn)號可以正常解析 2 .toString(); // 注意點(diǎn)號前面的空格 (2).toString(); // 2先被計(jì)算?
訪問100['toString']的length返回toString方法形參個數(shù);
換個
(function(a,b){//輸出2 })['length'] fn = {f : function(a,b,c){//3 } };fn.f['length']有長度屬性的函數(shù),這個長度就是用來計(jì)算多個參數(shù)的,
可以分解為
100['toString'].length由于toString是個方法,所以它length屬性返回的是toString的形參個數(shù),而toString方法可以接收一個radix(基數(shù))作為形參(比如:toString(2),返回該數(shù)值的二進(jìn)制,16則代表16進(jìn)制),所以最終返回結(jié)果是1。
function toString( [radix : Number] ) : Stringradix 可選項(xiàng)。為將數(shù)字值轉(zhuǎn)換為字符串指定一個基數(shù)。此值僅用于數(shù)字。
所以當(dāng)數(shù)字調(diào)用toString的時(shí)候,會有一個參數(shù)radix,其它的比如:Function、Array、String這些調(diào)用的話,結(jié)果會是 0
剛才上面的100['toString']['length']為什么不分解成100.toString.length?
這是是由于100后面的.是小數(shù)點(diǎn)之后是小數(shù)部分,從而導(dǎo)致語法錯誤
解決的方法也說了
100..toString.length 1參考資料
http://www.dengpeng.org/archives/615
?
題目4:結(jié)果是什么?
var a = (1,5 - 1) * 2- 0.999999999
- 1
- 0.5
- 8
- -0.5
- 4
這里主要是理解這個 逗號操作符了
在for循環(huán)中,增量表達(dá)式
j = 10; for (i = 0; i <5; i++, j++) {k = i + j;} i j k 0 10 10 1 11 12 2 12 14 3 13 16 4 14 18允許多個表達(dá)式被當(dāng)作單個表達(dá)式,所以這兩個變量可以遞增。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
?
當(dāng)有一個包含一個或多個逗號表達(dá)式,表達(dá)式的值等于最后一個值
var a = (1,2,3,4) //4* 逗號操作符的最佳用途是定義多個變量和示例使用這里是絕對不推薦的
答案呼之欲出了就是8,
?
題目5 結(jié)果是什么?
var x = 10; var foo = {x: 20,bar: function () {var x = 30;return this.x;} };console.log(foo.bar(), // 1.(foo.bar)(), // 2.(foo.bar = foo.bar)(), // 3.(foo.bar, foo.bar)() // 4. );- 20, 20, 20, 20
- 20, 20, 10, 10
- 20, 20, 20, 10
- 20, 20, 10, 30
- 20, 10, 10, 10
- 20, 10, 30, SyntaxError
我們一句一句的分解
foo.bar()這個很簡單,直接調(diào)用bar 方法,此時(shí)的上下文就是foo對象,所以this.x = 20? return 的結(jié)果也就是20了
?
(foo.bar)()我們看看括號的定義 ECMA語言規(guī)范
11.1.6 The Grouping OperatorThe production PrimaryExpression : ( Expression ) is evaluated as follows:1. Evaluate Expression. This may be of type Reference.2. Return Result(1).NOTE This algorithm does not apply GetValue to Result(1). The principal motivation for this is so that operators such as delete and typeof may be applied to parenthesised expressions.引用類型的值與函數(shù)上下文中的this值如何相關(guān)?——從最重要的意義上來說。 一個函數(shù)上下文中確定this值的通用規(guī)則如下:
在一個函數(shù)上下文中,this由調(diào)用者提供,由調(diào)用函數(shù)的方式來決定。如果調(diào)用括號()的左邊是引用類型的值,this將設(shè)為引用類型值的base對象(base object),在其他情況下(與引用類型不同的任何其它屬性),這個值為null。不過,實(shí)際不存在this的值為null的情況,因?yàn)楫?dāng)this的值為null的時(shí)候,其值會被隱式轉(zhuǎn)換為全局對象。注:第5版的ECMAScript中,已經(jīng)不強(qiáng)迫轉(zhuǎn)換成全局變量了,而是賦值為undefined。這是對組操作符的描述,說明得到的結(jié)果是一個 Reference 引用類型
alert( foo.bar === (foo.bar) ) //true關(guān)于引用類型的解釋,參考
http://dmitrysoshnikov.com/
?
(foo.bar = foo.bar)(),這一題我也做錯了,呵呵
查了查資料,我們先看看
var foo = { bar: function () { alert(this); alert(this === foo); } }; ?foo.bar(); // foo, true
var exampleFunc = foo.bar;
alert(exampleFunc === foo.bar); // true
// 再一次,同一個function的不同的調(diào)用表達(dá)式,this是不同的
exampleFunc(); // global, false
可見將foo.bar的引用賦給一個變量,在執(zhí)行的時(shí)候,這個this的指向就被改變了
?
重點(diǎn)(=)賦值是如何處理的?
不懂就翻規(guī)范唄,又去找找ECMA語言規(guī)范
11.13.1 Simple Assignment (= ) The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:1. Evaluate LeftHandSideExpression.2. Evaluate AssignmentExpression.3.Call GetValue(Result(2)).4.Call PutValue(Result(1), Result(3)).5.Return Result(3). 8.7.2 PutValue(V, W)1. If Type(V) is not Reference, throw a ReferenceError exception. 2. Call GetBase(V). 3. If Result(2) is null, go to step 6. 4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) for the property name and W for the value. 5. Return. 6. Call the [[Put]] method for the global object, passing GetPropertyName(V) for the property name and W for the value. 7. Return.我也沒有看太明白, 還要慢慢消化,但是大體的定義
賦值運(yùn)算符調(diào)用了GetValue方法。返回的結(jié)果是函數(shù)對象(但不是引用類型),這意味著this設(shè)為null,結(jié)果是global對象
語句返回的是 foo.bar 的函數(shù)值
因此,賦值操作符返回的是「值(Value)」而不是「引用(Reference)」。
因?yàn)楹瘮?shù)體需要 this 值獲取 x 屬性的值,那么接下來我們考慮改函數(shù)時(shí)調(diào)用時(shí)的上下文作用域以及背后的具體流程。 尤其注意第七條規(guī)則
... 6. If Type(Result(1)) is Reference, Result(6) is GetBase( Result(1)). Otherwise, Result(6) is null. 7. If Result(6) is an activation object, Result(7) is null. Otherwise,Result(7) is the same as Result(6). 8. Call the [[Call]] method on Result(3), providing Result(7) as the this value and providing the list Result(2) as the argument values. …那么在這種情況下,GetBase 操作實(shí)際上返回的是 null,因此此條語句函數(shù)執(zhí)行的作用域?yàn)?global ,在瀏覽器中也就是 window 。
(foo.bar = foo.bar)()那么,上面的語句中我們可以得知
找了幾篇相關(guān)文章具體參考:
http://www.w3.org/html/ig/zh/wiki/ES5/%E8%A1%A8%E8%BE%BE%E5%BC%8F
http://www.cnblogs.com/TomXu/archive/2012/01/17/2310479.html
?
(foo.bar, foo.bar)()逗號運(yùn)算符和邏輯運(yùn)算符(OR)調(diào)用了GetValue 方法,相應(yīng)地,我們失去了引用而得到了函數(shù)。并再次設(shè)為global。
?
我們似乎可以總結(jié)一下:
JavaScript 是弱類型語言,這就意味著,等于操作符會為了比較兩個值而進(jìn)行強(qiáng)制類型轉(zhuǎn)換。
兩個等號組成:==
"" == "0" // false 0 == "" // true 0 == "0" // true false == "false" // false false == "0" // true false == undefined // false false == null // false null == undefined // true " \t\r\n" == 0 // true嚴(yán)格等于操作符由三個等號組成:===
"" === "0" // false 0 === "" // false 0 === "0" // false false === "false" // false false === "0" // false false === undefined // false false === null // false null === undefined // false " \t\r\n" === 0 // false== 被廣泛認(rèn)為是不好編程習(xí)慣的主要原因, 由于它的復(fù)雜轉(zhuǎn)換規(guī)則,會導(dǎo)致難以跟蹤的問題。
此外,強(qiáng)制類型轉(zhuǎn)換也會帶來性能消耗,比如一個字符串為了和一個數(shù)字進(jìn)行比較,必須事先被強(qiáng)制轉(zhuǎn)換為數(shù)字。
關(guān)于Object.prototype.toString方法的原理參考
https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/toString
http://www.cnblogs.com/ziyunfei/archive/2012/11/05/2754156.html
?
后面還有5道題,樓主要深思熟慮才行…
JS越學(xué)越謙卑….
后面還有5道題,樓主要深思熟慮才行…
JS越學(xué)越謙卑….
后面還有5道題,樓主要深思熟慮才行…
JS越學(xué)越謙卑….
還有5道題,需要深思熟慮了...
PS:JS越學(xué)越謙卑........
轉(zhuǎn)載于:https://www.cnblogs.com/aaronjs/p/3339107.html
總結(jié)
以上是生活随笔為你收集整理的试试看 ? 离奇古怪的javascript题目的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 维护一套同时兼容 iOS 6 和 iOS
- 下一篇: 网页制作中最有用的免费Ajax和Java