前端冷知识(适用于学习积累和面试)

417 阅读11分钟

冷知识

1.parseInt(a,b),接受2个参数,表示将b进制下的a转为10进制数;而不是将十进制下的a转为b进制下的数。

parseInt(1,2);//1,将2进制下的1转为10进制下的数字,结果为1

parseInt(10,2);//2,将2进制下的10转为10进制下的数字,结果为2

parseInt(3,2);//NaN,将2进制下的3转为10进制下的数字,结果为NaN,因为任何一位的数都不能超过进制数。

parseInt(13,2);//1,将2进制下的13转为10进制下的数字,结果为1,因为任何一位的数都不能超过进制数,所以只能截取前面不超过的数,所以parseInt(13,2)实际上是parseInt(1,2),所以结果为1。

--第一个是要处理的值,期望是含数字的字符串(含有数字的字符串有非数字字符,最后只保留数字部分)。

parseInt(32);//32.    parseInt(‘32px’);//32

--第二个是进制基数,如果第一个参数不符合基数的进制规范,则尝试截取前面符合规范的部分,若截取不到合规的,转为NaN。接受范围为2到36。若不传,或传0则识别为10.

2.setTimeout,接受3个参数, --第一个为回调函数, --第二个为计时时间, --第三个为传入回调函数的参数

setTimeout(function(value){
    console.log(value);
},1000,100);
//大约一秒后输出100。

3.对象在底层表现为二进制,在js中,二进制前三位都是0的话就会被判定为object类型,而null二进制表示全是0,所以typeof时是object。

typeof null = ‘object’;

4.空数组执行reduce会抛错,因为reduce找不到初始值。

[].reduce(()=>{});
//Uncaught TypeError: Reduce of empty array with no initial value
//    at Array.reduce (<anonymous>)
//    at <anonymous>:1:4

5.在加号与三木运算符并存的表达式中,如果没有括号标识,那么加号的优先级高于三木运算符。

var a = 'world';
var b = 'hellow' + a === 'world' ? a : '';
console.log(b); // world

6.Math.pow(2, 53),也就是9007199254740992,再增加1返回的还是本身,但是增加2就会成功,

9007199254740992 + 1;//9007199254740992。
9007199254740992 + 2;//9007199254740994。

也就是说:

9007199254740992 + 奇数=9007199254740992 + 奇数-1.
9007199254740992 + 偶数=9007199254740992 + 偶数.

7.数组的filter方法在执行时若遇到空的元素,会忽略,而不执行该次回调。

var arr = [1,2,,,,2,1];
arr.filter(x=>{
    return x !== 2;
})
// [1, 1]

8.浮点型计算时精度丢失。

0.1 + 0.2 === 0.3  //false
0.1 + 0.2  // 0.30000000000000004

所以这种场景的判断方式是:

0.3 - (0.1 + 0.2) < Number.EPSILON // true
Number.EPSILON // 2.220446049250313e-16

9.new String('str') 与 String('str') 。

typeof new String('str'); //“object”,

new String('str')返回的实例有length,有每一个字符对应一个下标,PrimitiveValue即原始值为str

typeof String('str’) // “string”,

值为new String('str’)的原始值。 可以说new String('str’)相当于给’str'加了一层封装,还可以这样来封装:

var str = ’str’;
Object(str); // 返回的结果与new String('str’)一致。

解封的方法是使用valueOf,可以获取原始值:

var str = 'str';
var obj = Object(str);
obj.valueOf(); // "str"

10.数组的构造函数的原型对象是一个数组,即

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

只不过默认下Array.prototype.length为0. 因为所有的数组实例都要继承来自Array.prototype上的方法和属性,所以这样无疑更合理。

11.数组的map方法,当遇到空元素时,不走回调,而是直接将空元素返出去。

var arr =[];
arr.length = 4;
arr[0]=2
arr[3]=2
arr.map(function(elem) { return '1'; });
//["1", empty × 2, "1”]

12.常规函数(非箭头函数)中的arguments是一个数组对象,即一个引用类型(所以对其中各元素的修改会影响原数组),其中callee属性表示当前函数对象,length表示数组中的参数个数,即当前函数执行时传入的实参的个数。

function func(a,b,c){
	console.log(typeof arguments);//object
	
	console.log(arguments.callee);
	//ƒ func(a,b,c){
	// console.log(typeof arguments);
	// console.log(arguments.callee);
	// console.log(arguments.length);
    //}
    
	console.log(arguments.length);//2
}

13.Number.MIN_VALUE的值为5e-324,即5 / 10 ^324,所以Number.MIN_VALUE是大于0的;

Number.MIN_VALUE > 0;//true

14.不论数组嵌套多少层,数组的tostring方法都会把它拍平,然后把各个元素转换后的值链接成一个字符串。

[[[2,3,4]]].toString();   //'2,3,4'
[[[[],2,3,4,5],1]].toString(); //",2,3,4,5,1"
[[[{},2,3,4,5],1]].toString();// "[object Object],2,3,4,5,1”

15.逗号运算符:最后一个值,覆盖前面的值.

var val = (1,2,3);
console.log(val); // 3

16.关于数字与.的关系

1.toString(); //抛错
1..toString(); // '1'
1...toString();//抛错
.1.toString(); // '0.1'

原理分析: js中,当一个数字中有点(.)存在,不管是在数字里面还是数字左右两边(要跟数字是紧密连在一起的),第一个点(.)都会被识别为数字的一部分,第二个点才会被识别为点运算符。 js中,整数和小数都会统一被认为是数字类型,如果直接把数字中的点识别为点运算符,那么小数0.42中的点就无法判断其到底是小数点还是点运算符了,甚至可以被理解为0这个数字对象的名为42的属性,这显然是不对的,所以为了兼容小数的存在,把数字里面出现的第一个点(跟数字紧密联系在一起的)认为是数字的一部分,即小数点,而第二个点才被识别为点运算符。 解决:把1.toString();变为(1).toString();或者1 .toString();即可。

17.两个看起来一样的正则并不相等

var regA = /reg/;
var regB = /reg/;
regA == regB;//false
regA === regB;//false

因为typeof regA/typeof regB结果均为’object’。正常的对象类型都是引用类型,实际上都是存在堆内存里的,变量所持有的都只是地址,所以两个不同的正常的对象类型的地址是一定不相同的。

18.数组之间无法用 == 和 === 进行比较,但是可以使用 > 和 < 来进行比较。

var a=[10,20,30];
var b=[10,20,31];
a<b // true
var a=[10,20,30];
var b=[10,20,31];
a>b // false

19.函数拥有prototype属性,是一个对象,但是通过.prototype与getPrototypeOf获取的原型对象并不是同一个。

function func(){}
func.prototype === Object.getPrototypeOf(func); //false

因为func.prototype指的是由func实例化出来的实例的原型。而Object.getPrototypeOf(func)获取的对象指的是Function.prototype,而func是Function的实例。

20.函数对象拥有name属性,具名函数的name就是函数的名字,但是匿名函数的name是一个空字符串。

(function func(){}).name;//func
(function(){}).name;//''

该name是只读属性,一旦函数声明,不允许修改。

function func(){};
func.name = 'foo';
console.log(func.name);//func

21.函数实例的原型对象也拥有name属性,但是为空字符串(考虑到匿名函数)。

function func(){};
var proto = Object.getPrototypeOf(func);
proto.name // ''

22.eval方法会将函数的名字转译为函数本身.

function func(){};
eval('func');//function func(){}
typeof eval('func’); // 'function'

23.函数是有length属性的,length的值取决于该函数的形参的个数。

function func(a,b,c){}
func.length;//3

函数对象的构造函数也有length属性,

Function.length;//1

24.replace接受两个参数, 第一个参数可以为字符串或者一个正则表达式。 第二个参数为一串字符串或者一个函数,这个字符串或者这个函数的返回值来替换第一个参数在replace调用者中的匹配项。 当第一个参数为字符串或者为不加g规则的正则时,只替换匹配到的第一个。 当第一个参数为加了g规则的正则时,替换所有匹配到的项。 回调函数接受三个参数,第一个为本次匹配到的项,第二个为匹配项的偏移、索引,第三个为调用replace的调用者。

var str = '123123123';
str.replace('1','9'); //923123123
var str = '123123123';
str.replace('1',function(){return '9';}); //923123123
var str = '123123123';
str.replace(/1/,'9'); //923123123
var str = '123123123';
str.replace(/1/,function(){return '9';}); //923123123
var str = '123123123';
str.replace(/1/g,function(){return '9';}); //923923923
var str = '231';
str.replace(/1/g,function(a,b,c){
    console.log(a); //1
    console.log(b); // 2
    console.log(c); // '231'
}); 

25.正则的test方法在被传入null或者空时,会将null转化为’null’,将空转换为’undefined’。

var reg = /n/;
reg.test(null);//true
reg.test();//true

26.在定义数组时,javascript允许一个尾随逗号.

[1, 1, 1, ].join('*'); //"1*1*1"

27.在实例化Date函数的时候即new Date()的时候, --如果传入的参数为非数字且不是一个符合规则的日期字符串,那么返回的结果为’Invalid Date’,尽管它依然是一个实例对象,但他是无效的,因为时间在内部会保留为一个有效数字,但这个实例内部保留的是NaN。

new Date('sdfsdf'); // Invalid Date
new Date([]); //Invalid Date

--如果什么都不传入,返回的就是当天的标准时间对象

new Date();//Tue Aug 06 2019 19:15:18 GMT+0800 (中国标准时间)(是的,就是写这篇笔记的时间)

--如果传入的是一个符合规则的日期字符串,得到的就是对应的标准时间对象

new Date("2014-03-19”);//Wed Mar 19 2014 08:00:00 GMT+0800 (中国标准时间)

--如果传入的是一个有效数字,将识别为毫秒数,返回的值就是是1970年1月1日当天8点再加上传入毫秒数得到的时间的标准时间对象。

new Date(0); // Thu Jan 01 1970 08:00:00 GMT+0800 (中国标准时间)
new Date(1000); // Thu Jan 01 1970 08:00:01 GMT+0800 (中国标准时间)

--如果传入的是两个,第一个识别为年份,第二个识别为月份(此时的月份以0为始)

new Date(2019,1);// Fri Feb 01 2019 00:00:00 GMT+0800 (中国标准时间)

--如果传入的是三个,第三个识别为日期

new Date(2019,1,2); //Sat Feb 02 2019 00:00:00 GMT+0800 (中国标准时间)

--如果传入的是四个,第四个识别为小时

new Date(2019,1,2,12);//Sat Feb 02 2019 12:00:00 GMT+0800 (中国标准时间)

--如果传入的是五个,第五个识别为分钟

new Date(2019,1,2,12,12);//Sat Feb 02 2019 12:12:00 GMT+0800 (中国标准时间)

--如果传入的是六个,第六个识别为秒

new Date(2019,1,2,12,12,12);//Sat Feb 02 2019 12:12:12 GMT+0800 (中国标准时间)

--如果传入的是七个,第七个识别为毫秒,并且如果毫秒满足进位,则进位。

new Date(2019,1,2,12,12,12,1000);//Sat Feb 02 2019 12:12:13 GMT+0800 (中国标准时间)

28.Date函数执行的时候,不论里面传入的值是什么,又是什么类型,返回出来的都是当天的标准时间的日期字符串。

Date(0); //"Tue Aug 06 2019 19:03:55 GMT+0800 (中国标准时间)"
Date(100000); //"Tue Aug 06 2019 19:04:02 GMT+0800 (中国标准时间)"
Date('asdasdasdasdasdasd'); //"Tue Aug 06 2019 19:04:11 GMT+0800 (中国标准时间)"
Date([]); //"Tue Aug 06 2019 19:05:06 GMT+0800 (中国标准时间)"

29.执行Math.min()而不传参数的时候,得到的结果是Infinity,执行Math.max()而不传参数的时候,得到的结果是-Infinity。

Math.min();//Infinity
Math.max();//-Infinity

30.字符串的match方法,会将字符串转换为正则表达式,而不进行对特殊符号的转译。所以导致/会被.匹配到。

'/gif'.match('.gif’);//["/gif", index: 0, input: "/gif", groups: undefined]

写在最后

需要声明的一点是,我不是一个教授者,我只是一个分享者、一个讨论者、一个学习者,有不同的意见或新的想法,提出来,我们一起研究。分享的同时,并不只是被分享者在学习进步,分享者亦是。

知识遍地,拾到了就是你的。

既然有用,不妨点赞,让更多的人了解、学习并提升。