频道栏目
首页 > 程序开发 > web前端 > JavaScript > 正文
44个javascript变态题解析
2018-04-02 11:59:11         来源:duandianyiwai的博客  
收藏   我要投稿

44个javascript变态题解析。

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

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

ParseInt()字符串转为数值parseInt()只接受两个两个参数string, radix(基数,即多少进制).按照radix进制来转换string。parseInt(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种基本类型分别为:undefined、null、boolean、number、string。

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

什么是基本类型?

如:undefined、null、1、2、3、'hello'、"hi",可以理解为:基本类型,就是简简单单一个数值。

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

如:var o=newObject();

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

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

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指向对象的构造函数)

简单示例:

FunctionUser(){}

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()迭代数组所有项,构建一个最终返回值。Reduce,reduceRight()都接受两个参数,一个回调,一个初始值.回调函数接受四个参数 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 这个笔者实践了一下 发现 firefox是window, 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.合法啊!

点击复制链接 与好友分享!回本站首页
上一篇:jQuery选择器探究:Sizzle构造函数
下一篇:JavaScript开发之dojo文档相关模块
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站