JS-Array-Improved

parseInt

类似一些遍历类型的api:forEach、map,可能有人就说了:不就是arr.map(x=>x+1),要是涉及到索引,那就再来个index,arr.map((x,index)=>x+index),多简单是不是

然后,先抛出一个问到烂的面试题:
[‘1’,‘2’,‘3’].map(parseInt)
找工作的人,看过面试题的,都知道结果是[1,NaN,NaN],那么为什么会这样呢?
首先,map里面可以传两个参数:map(对每一个元素都调用的函数,该函数的this值)
而那个每一个元素都调用的函数,他传入的参数是(current,index,arr)当前元素(必须)、索引、数组。

在这个例子,对parseInt传入的就是这三个参数。
而parseInt这个原生的函数,他传入的参数是(num,radix):
radix表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN

parseInt(10,10)//对10进制数字10取整,10
parseInt(10,2)//对2进制数字10取整,2
parseInt(111,2)//对2进制数字111取整,7
parseInt(111,4)//对4进制数字111取整,21
parseInt('1',2,[1])//1,传入第三个数组是没有意义的
parseInt('1',2,['1','2','3','4'])//1
parseInt('2',2,['1','2','3','4'])//NaN,2进制没有2
parseInt('2',3,['1','2','3','4'])//3

那就很明显了,对于为什么是[1,NaN,NaN],其实就是:

parseInt('1',0,['1','2','3'])//1,radix为 0,则数字将以 10 为基础来解析
parseInt('2',1,['1','2','3'])//1进制是啥?反正就是NaN
parseInt('3',2,['1','2','3'])//2进制没有3

另外,parseInt,遇到字符串的数字他会尽量解释,直到不能解释就停止。

parseInt('123sfd')//123
parseInt('123sfd123')//123
parseInt('sfd213')//NaN

数组遍历的api第二个参数

第二个参数,表示前面那个函数内部的this,一般不填这个参数,严格模式this是undefined。而在非严格模式下,this指向window:

[1,2,3].forEach(function(x){console.log(this)})//window

我们可以强行把他改成其他的看看:

[1,2,3].forEach(function(x){console.log(this)},Math)//Math

用循环生成一个序列

生成一个序号数组:

var arr = [];
for(var i = 0;i<10;i++){
    arr.push(i)
}

常规操作,没什么问题,但是精通jQuery的你会不会用到其他方法呢? 比如:

Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函数
Array.apply(null, { '0':1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一样
Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true]
Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"]
Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]

对于最后一个结果,点开第二个看看

image

map的那个函数,传入了三个参数,第一个参数是当前元素。可是对于加了call的,第一个参数就是call的this指向了。而map后面的那个参数,就是this,也就是后面那个this已经把current覆盖,起到主导作用的也是后面那个参数。而map的第一个参数fn,fn里面的第二个参数是index,也就是当前索引。而对于f.call,第一个参数是this指向,第二个参数以后全是f.call的函数f所使用的参数。最后,就相当于对每一个元素进行,Number(index),Boolean(index),String(index),Object(index)

构造类

Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函数
Array.apply(null, { '0':1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一样
Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true]
Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"]
Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]

map第二个参数ctx是this指向,而第一个参数是一个函数f(任何函数),f的第一个参数已经报废,因为第一个参数是call的上下文this,但是这个this又被后面的ctx替代了,因此f有效的参数是从第二个开始,最后就相当于ctx(index),即是 :构造类(index)

于是我们又可以看看构造类另一个有意思的地方:

var toFixed = 1;
var obj = {
    toFixed:"我只是客串的",
    show:function(){
        return this. toFixed;
    }
}
obj.show.call( toFixed);   //ƒ toFixed() { [native code] }

也许一眼看上去是1,然而call的第一个参数居然不是null、undefined,效果不一样了。
我们call的上下文就是toFixed。可以这样理解,对于js内部,1其实是构造类Number(1)构造出来的,相当于this指向了Number,而我们可以打印一下Number.prototype,结果有

image

我们把toFixed方法打印出来了

对于String也是可以的

var big = '1sdasdsadsdasd';//不是字符串的话,其他构造类没有big方法,返回undefined
var obj = {
    big:"我是客串的",
    show:function(){
        return this.big;
    }
}
obj.show.call(big);  //ƒ big() { [native code] }

//或者说,打印一个length看看
var l = '1sdasdsadsdasd';//变量换成l
var obj = {
    length:"我是客串的",
    show:function(){
        return this.length;//主要是这个,变量是什么不重要
    }
}
obj.show.call(l); //14

属性太多了,可以去控制台看看String.prototype有什么。

再或者说,看看函数执行起来会发生什么事情:

var l = true;//这次试一下boolean类型
var obj = {
    length:"我是客串的",
    show:function(){
        return this.valueOf();//这次我们不打印这个函数了,让他执行
    }
}
obj.show.call(l,this); //true,直接调用类型转换过程中的那个valueOf

参考链接

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值