全网最详细的js数组slice底层原理详解(附js实现),深刻理解为何通过slice.call()可以将伪数组转为数组

首先js 数组底层也是一个对象
控制台输入以下

typeof [] //object

可见数组的类型本质上也是object对象

然后

typeof Array //function

可见数组类Array,本质上也是一个js函数类

接着

[1,2,3] instanceof Array //true

可见数组是数组类Array的实例
理解了以上内容后,
看一下数组对象的特征
控制台输入以下

[1,2,3]

得到一个数组对象,展开可以看到
0: 1
1: 2
2: 3
length: 3
[[Prototype]]: Array(0)
本质上是索引从0开始,包含length值,并且原型指向Array的对象

然后是伪数组

{0:1,1:2,2:3}

以上代码得到的不是数组,也不是伪数组
伪数组成立的最重要的一条就是需要有length,
例如

{length:1}
{a:1,length:9}
{1:1,length:3}

只要一个对象里存在值为number类型的”length“,那么就可以视为伪数组
常见的伪数组有函数内arguments对象,document的获取多个dom的方法

function test(){
	arguments //
}
document.getElementsByClassName('')

接下来看slice方法
抛开es6的Array.from({length:10})方法
Array的slice方法可以创建一个新的数组副本
不传入参数即为数组的浅拷贝

let aa=[1,2,3]
let bb=aa.slice();
aa===bb//false

简单写了以下slice的具体实现

Array.prototype._slice=function(){
	let startIndex,endIndex;
	if(arguments.length===2){
		startIndex=parseInt(arguments[0]);
		endIndex=parseInt(arguments[1])-1;
	}
	else if(arguments.length===1){
		let a = parseInt(arguments[0]);
		if(isNaN(a)){
			startIndex=0;
			endIndex=this.length-1;
		}
		else if(a<0){
			startIndex = this.length - Math.abs(a);
			endIndex = this.length-1;
		}
		else{
			startIndex = a;
			endIndex = this.length-1;
		}
	}
	else if(arguments.length==0){
		startIndex=0;
		endIndex=this.length-1;
	}
    if(isNaN(startIndex)||isNaN(endIndex)){
        return [];
    }
    else{
        let res = new Array(endIndex-startIndex+1);
        let index=0;
        for(let i=startIndex;i<=endIndex;i++){
            if(this[i]!=undefined){
                res[index]=this[i];
            }
            index++;
        }
        return res;
    }
}

可以测试一下,Array.prototype._slice.call和Array.prototype.slice.call是一样的
用.call可以将带有length的伪数组指向slice函数内的this,从而返回需要的数组对象。
网上很多都说是将原有的伪数组转成或者集成了数组的特性,其实都是错误的,实际上原来的伪数组对象根本没有任何变化。。。

顺便再写一下Array.from方法的实现

Array.prototype._from=function(obj){
    if(obj){
        if(typeof obj==='object'){
            let length = parseInt(obj.length);
            if(isNaN(length)||length<0){
                length=0;
            }
            let res = new Array(length);
            for(let i=0;i<length;i++){
                res[i]=obj[i];
            }
        }
        return [];
    }
    else{
        console.error("object is required")
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值