首先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")
}
}