43-JS puzzlers

QAQ List

Object.getPrototypeOf(Object.prototype)
constructor.prototype
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval eval需要注意

原题地址: http://javascript-puzzlers.herokuapp.com/ 简单解析:http://flyfy1.github.io/language/2014/02/23/js-tricks-from-js-puzzlers/

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

1

第一题注意的是参数的传入: parseInt(string,radix) map(value,index,array) 参数数量不同 https://segmentfault.com/a/1190000000411840

2

关键点: typeof 、instanceof 、null https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null
https://developer.mozilla.org/en-US/docs/Glossary/Primitive 原始数据类型

A primitive (primitive value, primitive data type) is data that is not an object and has no methods. In JavaScript, there are 6 primitive data types: string, number, boolean, null, undefined, symbol (new in ECMAScript 2015).
所以此题考查两个操作符 & null。 null属于原始数据类型,并没有原型对象

null

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是0。由于 null 代表的是空指针(大多数平台下值为0x00),因此,null的类型标签也成为了0,typeof null就错误的返回了"object".

包装类型:Primitive wrapper objects

Except for null and undefined, all primitive values have object equivalents that wrap around the primitive values: https://developer.mozilla.org/en-US/docs/Glossary/Primitive

  • String for the string primitive. 也就是字符串对象,有方法和函数
  • Number for the number primitive.
  • Boolean for the Boolean primitive.
  • Symbol for the Symbol primitive.

The wrapper's valueOf() method returns the primitive value.

字符串为例:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String

String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (i.e., without using the new keyword) are primitive strings. JavaScript automatically converts primitives to String objects, so that it's possible to use String object methods for primitive strings. In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup.

4

优先级: + operator has higher precedence than the ternary one.

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

console.log('Value is ' + (val === 'smtg')) // Value is true 先是执行 + 然后才是 三元操作符  

5

作用域与变量提升的问题。

var name = 'World!';  
(function () {
    if (typeof name === 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

6

http://javascript.ruanyifeng.com/grammar/number.html

数字精度

根据国际标准IEEE 754,64位浮点数格式的64个二进制位中,第0位到第51位储存有效数字部分(共52位),第52到第62位储存指数部分,第63位是符号位,0表示正数,1表示负数。

因此,JavaScript提供的有效数字的精度为53个二进制位(IEEE 754规定有效数字第一位默认总是为1,不保存在64位浮点数之中,这一位再加上后面的52位,就是总共53位),也就是说,绝对值小于2的53次方的整数,即-(253-1)到253-1,都可以精确表示。

https://en.wikipedia.org/wiki/Double-precisionfloating-pointformat WIKI: 双精度浮点数格式
图示

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number 实例、方法、属性

Math.pow(2, 53)  
// 9007199254740992  精度 不是大小

Math.pow(2, 53) + 1  
// 9007199254740992

Math.pow(2, 53) + 2  
// 9007199254740994

Math.pow(2, 53) + 3  
// 9007199254740996

Math.pow(2, 53) + 4  
// 9007199254740996

表示形式

字面形式直接表示,也可以采用科学计数法

123e3 // 123000  
123e-3 // 0.123  
-3.1E+12
.1e-23

JavaScript会自动将数值转为科学计数法表示:
1. 小数点前的数字多于21位。

1234567890123456789012  
// 1.2345678901234568e+21
123456789012345678901  
// 123456789012345680000
  1. 小数点后的零多于5个。
0.0000003 // 3e-7  
0.000003 // 0.000003  

进制

使用字面量(literal)时,JavaScript对整数提供四种进制的表示方法:十进制、十六进制、八进制、2进制

十进制:没有前导0的数值。 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的七个阿拉伯数字的数值。 十六进制:有前缀0x或0X的数值。 二进制:有前缀0b或0B的数值。

其余

  • 0 +0 -0
  • NaN
  • infinity

方法

  • parseInt() parseInt的返回值只有两种可能,不是一个十进制整数,就是NaN
  • parseFloat() 用于将一个字符串转为浮点数。

Math

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math

Math is a built-in object that has properties and methods for mathematical constants and functions. Not a function object.

常用:

  • Math.abs(x) absolute value 绝对值
  • Math.ceil(x) Returns the smallest integer greater than or equal to a number. 小于等于
  • Math.round(x) 四舍五入
  • Math.floor(x) Returns the largest integer less than or equal to a number. 大于等于
  • Math.cbrt(x) Return the cube root of a number 立方
  • Math.sqrt(x) Returns the positive square root of a number. 平方
  • Math.max([x[, y[, …]]]) Returns the largest of zero or more numbers. 最大值
  • Math.min() 最小值
  • Math.pow(x,y) Returns base to the exponent power, that is, baseexponent. 指数
  • Math.random() a pseudo-random number between 0 and 1. 随机数(0-1)

8

var two   = 0.2  
var one   = 0.1  
var eight = 0.8  
var six   = 0.6  
console.log(two - one == one, eight - six == two)  

JavaScript does not have precision math, even though sometimes it works correctly.
Floating Point equality check will most-of-time give you unexpeced result
这题真的是。。。 注意这个0.8 吧 SO dangerous floating point values

9

switch uses = internally switch 用的是严格相等,平时确实没注意这个。

10

'A' === new String('A')  
//false
'A' === String('A')  
//true

11

var a = [0];  
if ([0]) {  
  console.log(a == true);
} else {
  console.log("wut");
}

[0] as a boolean is considered true. Alas, when using it in the comparisons it gets converted in a different way and all goes to hell. 就是作为单独的布尔值 是true ,如果进行比较的化,就是false。 操蛋

15

console.log("([ [] == [], [] === [] ]) = " + [ [] == [], [] === [] ]);  
// ([ [] == [], [] === [] ]) = false,false

is the spawn of satan. 都是false

17

 1 + - + + + - + 1
 // 2
 1 + - + + + 1
 //0

No mater how many + in front of a number, its sign is decided by the # of -

19

The result is 21, in javascript variables are tied to the arguments object so changing the variables changes arguments and changing arguments changes the local variables even when they are not in the same scope.

function bar(a,b,c) { c = 10; console.log(arguments); }
bar(1,1,1); // as we can see, arg c has been modified.
// [1,1,10]

21

What the fuck

http://stackoverflow.com/questions/21978707/calling-array-prototype-reverse-on-empty-array

// 可以这么玩
var x = Math.random;  
x()  
// 0.9481355238240212

22

WTF

2 [[[2]]]
// true

25

3.toString()  
3..toString()  
3...toString()  

WAHT THE FUCK

26

(function(){
  var x = y = 1;
})();
console.log(y);  
console.log(x);  

作用域问题: 相当于: y = 1; global
var x=y; function scope

27

var a = /123/,  
    b = /123/;
a == b      // flase  
a === b    //  false  

Per spec Two regular expression literals in a program evaluate to regular expression objects that never compare as = to each other even if the two literals' contents are identical.

Interestingly, regex are never equal to each other.

28

var a = [1, 2, 3],  
    b = [1, 2, 3],
    c = [1, 2, 4]
a ==  b  // false  
a === b  // false  
a >   c  // false  
a <   c  // true  
[] == []  //false
[] === [] //false

正如提到过的: 数组不能用 ===== 做比较 但可以使用 > <

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equalitycomparisonsand_sameness 一个相等表格

说明:

= 相等比较的问题

对于数组、正则。。来说,是对象 Object 所以比较时,不是比较其大小,而是比较在内存中的位置。所以不会相等。 对于基本类型来说,当然相等。

5 == 5  基本类型  
// true
new Number('5') == new Number('5')  对象  
// false 

30

function f() {}  
var a = f.prototype, b = Object.getPrototypeOf(f);  
a === b  //false  

f.prototype is the object that will become the parent of any objects created with new f while Object.getPrototypeOf returns the parent in the inheritance hierarchy.

31

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

name is a read only property. Why it doesn't throw an error when assigned, I do not know.

32

"1 2 3".replace(/\d/g, parseInt)  //  "1 Nan 3"
"1 2 3".replace(/\d/g, function(){console.log(arguments);}); // [1, 0], [2, 2], [3, 4].

String.prototype.replace invokes the callback function with multiple arguments where the first is the match, then there is one argument for each capturing group, then there is the offset of the matched substring and finally the original string itself. so parseInt will be invoked with arguments [1, 0], [2, 2], [3, 4].

33

function f() {}  
var parent = Object.getPrototypeOf(f);  
f.name // ?  
parent.name // ?  
typeof eval(f.name) // ?  
typeof eval(parent.name) //  ?  

"f", "Empty", "function", error

38

var a = Function.length,  
    b = new Function().length
a === b  

It's false. Function.length is defined to be 1. On the other hand, the length property of the Function prototype object is defined to be 0.

Because Function.length returns the # of args expected to this funciton.
Function() by default take 1 arg; annoymus function take 0 arg in stead.

WTF

39

var a = Date(0);  
var b = new Date(0);  
var c = new Date();  
[a === b, b === c, a === c]

When Date is invoked as a constructor it returns an object relative to the epoch (Jan 01 1970). When the argument is missing it returns the current date. When it is invoked as a function, it returns a String representation of the current time.

Date()

40

var min = Math.min(), max = Math.max()
min < max // false

Math.min returns +Infinity when supplied an empty argument list. Likewise, Math.max returns -Infinity.