44个javascript变态题解析上

声明:参考https://segmentfault.com/a/1190000005681454

新加了一些基础知识。加强对基础知识的巩固。

数值转换:(非数值转为数值)

Number() 可以用于任何数据类型。null->0  undefined->NaN对象:valueof() ,如果转换结果为NaN,调用对象的tostring()转为字符串,再按字符串的转换规则返回值。    字符串:(1)只包含数字,直接转为十进制数值(2)包含浮点格式,转为对应的浮点数(3)包含十六进制的,转为大小相同的十进制(4)字符串为空,转为05)字符串包含上述格式以外的字符,转为NaN

ParseInt() 字符串转为数值parseInt()只接受两个两个参数string, radix(基数,即多少进制).按照radix进制来转换stringparseInt(string,radix)的参数radix必须介于2~36之间,而且字符串string中的数字不能大于radix才能正确返回数字结果值。当参数radix 的值为0,或没有设置该参数时,parseInt()会根据string 来判断数字的基数。如果 string 以"0x"开头,parseInt()会把string 的其余部分解析为十六进制的整数。如果 string 以 0 开头,那么ECMAScript v3允许parseInt()的一个实现把其后的字符解析为八进制或十六进制的数字。如果string 以1 ~ 9 的数字开头,parseInt()将把它解析为十进制的整数。

在没有指定基数,或者基数为 0 的情况下,JavaScript作如下处理:

•如果字符串 string "0x"或者"0X"开头,则基数是16 (16进制).

•如果字符串 string "0"开头,基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环景决定。ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值。

•如果字符串 string 以其它任何值开头,则基数是10 (十进制)

ParseFloat()字符串转为数值.。与ParseInt()类似,但第一个小数点有效,只解析十进制数值,16进制解析后被转换为0.

数组的5种迭代方法:每个方法接受两个参数,一个回调函数callback,一个回调函数的this值。其中回调函数接受三个参数:item(数组项的值), index(数组项在数组中的位置), arrary(数组对象本身);

Every()对数组中的每一项运行给定函数,如果该函数的每一项都返回true,则返回true

Some() 对数组中的每一项运行给定函数,如果该函数的某一项返回true,则返回true

Filter() 对数组中的每一项运行给定函数,返回true的项组成的数组。  

Map() 对数组中的每一项运行给定函数,返回每项函数调用的结果组成的数组

ForEach()对数组中的每一项运行给定函数,该函数没有返回值。

第一题:["1", "2", "3"].map(parseInt)

parseInt即为map()的回调函数,根据回调函数函数接收的参数和parseInt本身接收的参数,对比,本题即问

parseInt('1', 0);

parseInt('2', 1);

parseInt('3', 2);

parseInt('2', 1)parseInt('3', 2); 当参数radix 的值为0,或没有设置该参数时,parseInt()会根据string 来判断数字的基数。如果string 以1 ~ 9 的数字开头,parseInt()将把它解析为十进制的整数.而且字符串string中的数字不能大于radix才能正确返回数字结果值。

所以答案是  [1, NaN, NaN]

  var a=["1", "2", "3", "4","5",6,7,8,9,10,11,12,13,14,15];  

a.map(parseInt);  

返回结果为:[1,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,9,11,13,15,17,19]

 

javascript中,有5中基本类型,

5种基本类型分别为:undefinednullbooleannumberstring

除了基本类型,还有引用类型。

什么是基本类型

如:undefinednull123'hello'"hi",可以理解为:基本类型,就是简简单单一个数值。

什么是引用类型?(引用类型,也就对象类型)

如:var o=newObject();

Var d=new Date; //jsnew对象的时候,括号是可以省略的

//以上的od,就是引用类型,不再是一个简单的数值。

Typeof运算符

typeof 返回一个表示类型的字符串.

typeof的结果请看下表:

  

type        

Undefined 

undefined” 

Boolean

"Boolean"

Number

"Number"

String 


"string"

Function

"function"

Object

"Object/null"

  
  

注:    typeof运算符对于null值会返回"object"

在引用类型值判断类型的时候,typeof运算符会出现一个问题,无论引用的是什么类型的对象,它都返回"object"

ECMAScript引入了另一个Java运算符instanceof来解决这个问题。instanceof能判断一个值具体是由什么构造函数构造出来的。

function Person(){}

function User(){}

var u=new User;

console.log( u instanceof Person ); //false

console.log( u instanceof User ); //true

 

Object.constructor属性

javascript中的所有对象都继承自Object。

constructor是Object的一个属性,他指向:创建对象的函数的引用(指针)。(可以理解为constructor指向对象的构造函数)

简单示例:

  Function User(){}

var u=new User;

console.log(u.constructor===User );//得到true,也就是说对象的constructor属性指向他的构造函数。

console.log(u.constructor.name );//得到User,也就是构造函数的名称

注:constructor属性并非一定指向构造函数,他也是可以修改、变更的

[typeof null, null instanceof Object]

所以答案  [object, false]

Array归并方法:   redude()   reduceRight()迭代数组所有项,构建一个最终返回值。ReducereduceRight()都接受两个参数,一个回调,一个初始值.回调函数接受四个参数  previousValue, currentValue, currentIndex, array

需要注意的是  If the array is empty and no initialValue was provided, TypeError would be thrown.

3题:

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

答案 9  an error

Math对象

Math.ceil()向上取整          Math.min()  求数组中最小     Math.max()求数组中最大

Math.floor()向下取整           Math.random()  返回[0,1)之间的随机数

Math.round()四舍五入    Math.abs(num)    Math.exp(num)  Math.pow(num,pow)    Math.log(num)  Math.sqrt(num) Math.acos(num) Math.asin(num) Math.atant2(num) Math.cos(num)   Math.sin(num)    Math.tant(num)

第四题:

var val = 'smtg';

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

两个知识点:

•Operators/Operator_Precedence

•Operators/Conditional_Operator

简而言之  +  的优先级 大于  ?

所以原题等价于  'Value is true' ? 'Somthing' : 'Nonthing'  而不是  'Value is' + (true ? 'Something' : 'Nonthing')

答案  'Something'

 

提升:

JavaScript中,function声明 和variables会被提升。function声明是在执行代码之前会读取函数声明。Function表达式则不会提前读取。

变量提升是JavaScript将声明移至作用域scope (全局域或者当前函数作用域)顶部的行为。

5

var name = 'World!';

(function () {

    if (typeof name === 'undefined') {

        var name = 'Jack';

        console.log('Goodbye ' + name);

    } else {

        console.log('Hello ' + name);

    }

})();

等价于

var name = 'World!';

(function () {

    var name;

    if (typeof name === 'undefined') {

        name = 'Jack';

        console.log('Goodbye ' + name);

    } else {

        console.log('Hello ' + name);

    }

})();

所以答案是  'Goodbye Jack'

 

6

JavaScript中的稀疏数组与密集数组

一般来说,JavaScript中的数组是稀疏的,也就是说,数组中的元素之间可以有空隙,因为一个数组其实就是一个键值映射.本文解释了如何创建稀疏数组和不稀疏的数组.

译者注:实际上,JavaScript并没有常规的数组,所有的数组其实就是个对象,只不过会自动管理一些"数字"属性和length属性罢了.说的更直接一点,JavaScript中的数组根本没有索引,因为索引应该是数字,JavaScript中数组的索引其实是字符串.arr[1]其实就是arr["1"],arr["1000"] = 1,arr.length也会自动变为1001.这些表现的根本原因就是,JavaScript中的对象就是字符串到任意值的键值对.注意键只能是字符串.这和AWK类似.不信可以试试awk 'BEGIN{a[1]=1;print(a["1"])}'.也许这是因为Brendan Eich在发明JavaScript参考了不少awk的设计的原因.不过目前,ES6中已经有了类似于Java等语言的Map类型,键可以是任意类型的值.请参考我翻译的MDN文档Map

var ary = [0,1,2];

ary[10] = 10;

ary.filter(function(x) { return x === undefined;});

答案是  []

也就是说 从 3 - 9 都是没有初始化的''!,这些索引并不存在与数组中.array的函数调用的时候是会跳过这些''.

 

var ary = Array(3);

ary[0]=2

ary.map(function(elem) { return '1'; });

答案是:Array [ "1", <2 个空的存储位置> ]

 

7

Switch()比较值时使用的是全等操作符===,不会发生类型转换

function showCase(value) {

    switch(value) {

    case 'A':

        console.log('Case A');

        break;

    case 'B':

        console.log('Case B');

        break;

    case undefined:

        console.log('undefined');

        break;

    default:

        console.log('Do not know!');

    }

}

showCase(new String('A'));

答案是  'Do not know!'

switch 是严格比较, String实例(对象)和 字符串不一样.

function showCase2(value) {

    switch(value) {

    case 'A':

        console.log('Case A');

        break;

    case 'B':

        console.log('Case B');

        break;

    case undefined:

        console.log('undefined');

        break;

    default:

        console.log('Do not know!');

    }

}

showCase2(String('A'));

答案  'Case A'

使用NEW调用基本包装类型的构造函数与直接调用同名的转型函数(将任何数据类型转为string/Boolean/number基本类型)是不一样的。

String('A')   保存的是基本类型string的字符串    (p34)js高级程序设计

new String('A')   保存的是string的实例。

 

8

Array.isArray(Array.prototype); // true

一个鲜为人知的实事:  Array.prototype => [] ;

 

9

var a = [0];

if ([0]) {

  console.log(a == true);

} else {

  console.log("wut");

}

解析:

• Boolean([0]) === true

•[0] == true ◦true 转换为数字 => 1

[0] 转化为数字失败, 转化为字符串 '0', 转化成数字 => 0

0 !== 1

答案:  false

 

10

[] ==[] false  [] == ![]true[] == {}false

[] == [] 这个好理解.当两个值都是对象(引用值),比较的是两个引用值在内存中是否是同一个对象. 因为此[]非彼 [],虽然同为空数组,确是两个互不相关的空数组,自然==false. 

[] == ![] 这个要牵涉到 JavaScript中不同类型==比较的规则,具体是由相关标准定义的. ![]的值是false,此时表达式变为[] == false,参照标准,该比较变成了[] == ToNumber(false),[] == 0.这个时候又变成了ToPrimitive([]) == 0,'' == 0,接下来就是比较ToNumber('') == 0,也就是0 == 0,最终结果为true.在犀牛书49页,任意数组转换为字符串"",数字0和布尔值true

所以![]会转为布尔值true再取反false

然后根据相等运算符“==”的规则,有boolean的转为数字,有Object的转为原始值

左右两边会变成“” == 0

最后如果是字符串和数字比较,会把字符串转为数字0 == 0

结果就是为true

  []=={}//false [] == []//false是因为两个对象比较时候,比较的是引用,数组也是对象

基本类型比较时(string/number/boolean),比较的是他们的值,object/array/function比较的是他们的引用。

 

11

function sidEffecting(ary) {

  ary[0] = ary[2];

}

function bar(a,b,c) {

  c = 10

  sidEffecting(arguments);

  return a + b + c;

}

bar(1,1,1)

 

这是一个大坑, 尤其是涉及到ES6语法的时候

知识点:

•Functions/arguments

首先  The arguments object is an Array-like object corresponding to the arguments passed to a function.

也就是说  arguments  是一个  object , c就是arguments[2],所以对于c的修改就是对arguments[2]的修改.

所以答案是  21 .

然而当函数参数涉及到  any rest parameters, any default parameters or any destructured parameters  的时候,这个arguments就不在是一个  mapped arguments object  .....

 

请看:

function sidEffecting(ary) {

  ary[0] = ary[2];

}

function bar(a,b,c=3) {

  c = 10

  sidEffecting(arguments);

  return a + b + c;

}

bar(1,1,1)

答案是  12  

 

12

var a = 111111111111111110000,

   b = 1111;

a + b;

答案是:111111111111111110000

 

13

var x = [].reverse;

x();

 

知识点:

•Array/reverse

 The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array.

也就是说 最后会返回这个调用者(this), 可是x执行的时候是上下文是全局.那么最后返回的是  window .

补充:

@stellar91 这个笔者实践了一下 发现 firefoxwindow, chrome报错  VM190:2 Uncaught TypeError: Array.prototype.reverse called on null or undefined()  可能是实现不同,chrome中应该是对调用者做了检查.

 

Number.MIN_VALUE > 0

答案: true

14

MIN_VALUE 属性是 JavaScript中可表示的最小的数(接近0,但不是负数)。它的近似值为5 x 10-324

 

15

3.toString()

3..toString()

3...toString()

答案是 error, '3', error

 

你如果换一个写法就更费解了

var a = 3;

a.toString()

这个答案就是 '3';

 

为啥呢?    

因为在 js 1.1, 1., .1都是合法的数字.那么在解析3.toString的时候这个.到底是属于这个数字还是函数调用呢?只能是数字,因为3.合法啊!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值