声明:参考https://segmentfault.com/a/1190000005681454
新加了一些基础知识。加强对基础知识的巩固。
数值转换:(非数值转为数值)
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指向对象的构造函数)
简单示例:
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()迭代数组所有项,构建一个最终返回值。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.合法啊!