扫码关注官方订阅号
这个结果是把{0:1,length:1}这个对象转成[1]
我的理解apply的第一个参数是 调用slice 的对象,
可是slice不是数组的方法么,对象怎么能调用? 还有这个slice方法都没传参数,
我想知道怎么实现这个对象转数组的
光阴似箭催人老,日月如移越少年。
slice可以处理array-like object,即这个object可以.length并且可以通过数字下标取到相应的值时候,slice就会像处理对象一样处理。解释
array-like object
.length
javascript中类似“length属性存放长度,0开始的整数key存放数据”的对象很多场景下都可以被视作数组(array-like objects)。内置的多数(未验证是否所有)数组方法都是可以作用于任何array-like object上的。比如push也有类似的行为
(注意因为undefined被视为0,所以甚至连length属性都没有的时候也一样能工作)
也就是这些数组的内置方法其实只依赖length指示长度和整数下标存放内容而已,这是弱类型语言常见的“鸭子类型”思想
常用slice,或者说slice有转换的效果,是因为slice的行为不是修改原有的对象(数组),而是新建一个数组存放slice的结果。至于不传参数默认0之类的,就是默认参数呗
对象不是直接调用slice方法,而是通过apply,将slice方法中的this指向该对象。 JavaScript中的数组也可以看成是这样的对象
var array = [1, 2, 3]; var obj = { 0: 1, 1: 2, 2: 3, length:3 }
注意了,这个length属性很重要,有了length就可以像数组一样遍历这个对象了。
再来实现一个简单的slice方法,
function slice(start, end) { var array = []; start = start ? start : 0; end = end ? end : this.length; for (var i = start, j = 0; i < end; i++, j++) { array[j] = this[i]; } return array; }
例如楼主举例的数据,代入方法中一步步执行下,就明白怎么回事了。 说白了这个对象{0:1,length:1}在这种情况下可以看成[1]
Array.prototype.slice.apply({0:1,length:1}); 在这种情况下就相当于 var array=[1]; array.slice();
先假定楼主理解Array.prototype.slice.apply({0:1,length:1});中的Array和slice。
Array.prototype.slice.apply({0:1,length:1});
Array
slice
然后只要理解prototype和apply还有Array与object之间的关系的就行了。(最后还有this的说明)
prototype
apply
js是面向对象的,所有函数都有它的属性,和prototype,例子
//代码片段1 function Array(){ this.length = 5; } Array.prototype.slice = function(){} //上面的函数名,属性名,均直接使用了和数组一样的名字,这样好理解。
其中this.length是方法Array的属性,我们要获取这个值可以这样
this.length
//代码片段2 var a = new Array(); console.log(a.length);//5 //要调用Array()的方法slice,可以使用: a.slice();
结论:看了上面的用法,是不是和平时使用的数组很像?其实js的Array就是用与代码片段1差不多的方法写的,所以a.slice()是一个函数,所以Array.prototype.slice()是Array的一个方法,只是这个方法放在Array.prototype里。
a.slice()
Array.prototype.slice()
Array.prototype
prototype可以给一个函数定义一个子方法,该子方法能拿到函数的所有属性。(ps.你知道,slice()必须知道一个已知的数组才能返回选定的元素的吧?但是这个已知的数组却没有作为参数传递给slice(),这时slice()要怎么才知道要从哪个已知数组返回元素?答案是在slice()中使用this拿到当前数组的所有元素。因为在Array()肯定有一个或者多个属性,是保存着数组的所有元素的。)
slice()
this
Array()
是所有函数都具有的方法,就像所有Array都有slice方法一样,只要在函数后加上.apply()就能用了。这个方法的功能是调用函数,并且可以修改函数内的this和传入函数的参数。
.apply()
先说说apply()的参数,有两个,第一个用于修改函数内的this,第二个参数是数组,数组中的每个项都是传到调用apply()的函数中的参数,相当于函数中的arguments。
apply()
而Array.prototype.slice()中,this是指Array(),如果实例化过Array()(var a = new Array();)则是指a,也就是一个数组。
var a = new Array();
a
所以Array.prototype.slice.apply(a,[])等于a.slice()。 所以Array.prototype.slice.apply([1]);等于[1].slice()等于var a=[1]; a.slice()
Array.prototype.slice.apply(a,[])
Array.prototype.slice.apply([1]);
[1].slice()
var a=[1]; a.slice()
你会发现下面这个有趣的事情
var a=[1,2]; console.log(typeof a);//object
其实数组是一个特殊的object对象,[1,2]约等于{0:1,1:2,length:2},这里是约等于哦,因为直接使用var a={0:1,1:2,length:2}实例化的是Object,不是Array是不能用数组的专用方法的哦,如push、slice,会提示undefined is not a function是找不到此方法的意思。
[1,2]
{0:1,1:2,length:2}
var a={0:1,1:2,length:2}
push
undefined is not a function
但是此方法本身是可以处理这种格式的“数组”的,只是这个方法不在Object下,也不在Object.prototype下而已,所以不能使用a.slice(),所以才有了通过prototype直接访问slice方法,再使用apply重新指向它的this,就可以使用slice了。
Object
Object.prototype
我以前也是不理解this是什么东西,好像在不同地方有不同的用法一样,但是现在发现,其实就只有一种用法,往细了来说,最多两种。
下面括号中的一段删除,因为我发现我错了,this的理解看来不是我想的那样,抱歉,但是用法是没错的 (this,可以把它看做是函数的一个隐藏参数、默认参数,默认情况下该参数等于此函数,即:
function a(this){console.log(this)} a(); //可以自己试试输出的是什么,试的时候去掉参数位置的this
当this为默认值的时候,可以说它的功能就是给该函数添加属性,以及访问该函数的属性。)
而如果该函数是在其它函数(后面称为a函数)的prototype内,那this指的是a函数,也可以是该函数,也可以是其它a函数prototype内的其它函数,因为这时候定义的属性在其它prototype内的函数都能访问。
那么问题来了,使用jquery event的时候,回调函数内的this为什么指代的是触发事件的DOM?实质上,只要使用apply(),你可以把函数内的this参数改为任何东西。
jquery event
DOM
最后再结合对象来说,一个函数可以看作是一个对象,this在默认情况下指的就是这个对象的意思,this在哪个对象内,指的就是哪个对象。所以可以给对象添加属性,方法。
楼上说得有点复杂了,我试着简单的说下: slice的参数为(start, [.end]),start为必需 看再楼主的题目:Array.prototype.slice.apply({0:1, length:1}) 也就是说其实slice方法是没有传参数的 那么start就是undefined slice方法中如果没有设置start,start就是0,可通过如下证明[1,2].slice(); // [1,2] end如果没有指定,就是当前对象的length属性的值,也就是1 那么结果就是{0:1}.slice(0, 1); // 这是伪代码哈 返回一个新的数组,从对象中0开始,到1结束,也就是取对象下标为0的值。 {0:1}[0] => 1; 所以返回[1] 如果这样写Array.prototype.slice.apply({0:1, length:3}) 结果就应该是[1, undefined, undefined]
Array.prototype.slice.apply({0:1, length:1})
[1,2].slice(); // [1,2]
Array.prototype.slice.apply({0:1, length:3})
[1, undefined, undefined]
楼上几位回答很不错,但说的太细可能会让楼主略感迷茫...我来个简化版的
数组的切割方法,它返回的是一个被切割数组的副本,例如:
javascript [0,1,2].slice();//[0, 1, 2] [0,1,2].slice(0);//[0, 1, 2] [0,1,2].slice(0,1);//[0]
javascript
[0,1,2].slice();//[0, 1, 2] [0,1,2].slice(0);//[0, 1, 2] [0,1,2].slice(0,1);//[0]
注意,它返回的是一个被切割的数组的副本。
apply和call是把一个方法借给另外一个对象,最著名的就是类型判定:
call
javascript(1).toString();//"1" Object.prototype.toString.call(1);//[object Number]
(1).toString();//"1" Object.prototype.toString.call(1);//[object Number]
slice是通用的,这个通用的是如何定义的呢? 因为数组本身就是特殊的对象,那么数组的方法也可以借给一些和数组行为相似对象。当一个对象拥有和数组一样的特性,那么就可以使用slice。
javascript['a','b'].slice(1);//["b"] Array.prototype.slice.call({'0':'a','1':'b',length:2},1);//["b"]
['a','b'].slice(1);//["b"] Array.prototype.slice.call({'0':'a','1':'b',length:2},1);//["b"]
那么这个对象就拥有了和数组相似的特性,就可以使用Array的通用方法slice。 本质上,楼主的代码,实现的就是apply就是把数组的slice(),借给拥有和数组一样特性的对象。
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
扫描下载App
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
slice可以处理
array-like object
,即这个object可以.length
并且可以通过数字下标取到相应的值时候,slice就会像处理对象一样处理。解释javascript中类似“length属性存放长度,0开始的整数key存放数据”的对象很多场景下都可以被视作数组(array-like objects)。内置的多数(未验证是否所有)数组方法都是可以作用于任何array-like object上的。比如push也有类似的行为
(注意因为undefined被视为0,所以甚至连length属性都没有的时候也一样能工作)
也就是这些数组的内置方法其实只依赖length指示长度和整数下标存放内容而已,这是弱类型语言常见的“鸭子类型”思想
常用slice,或者说slice有转换的效果,是因为slice的行为不是修改原有的对象(数组),而是新建一个数组存放slice的结果。至于不传参数默认0之类的,就是默认参数呗
对象不是直接调用slice方法,而是通过apply,将slice方法中的this指向该对象。
JavaScript中的数组也可以看成是这样的对象
注意了,这个length属性很重要,有了length就可以像数组一样遍历这个对象了。
再来实现一个简单的slice方法,
例如楼主举例的数据,代入方法中一步步执行下,就明白怎么回事了。
说白了这个对象{0:1,length:1}在这种情况下可以看成[1]
先假定楼主理解
Array.prototype.slice.apply({0:1,length:1});
中的Array
和slice
。然后只要理解
prototype
和apply
还有Array与object之间的关系的就行了。(最后还有this的说明)prototype
js是面向对象的,所有函数都有它的属性,和
prototype
,例子其中
this.length
是方法Array的属性,我们要获取这个值可以这样结论:看了上面的用法,是不是和平时使用的数组很像?其实js的
Array
就是用与代码片段1差不多的方法写的,所以a.slice()
是一个函数,所以Array.prototype.slice()
是Array
的一个方法,只是这个方法放在Array.prototype
里。prototype
可以给一个函数定义一个子方法,该子方法能拿到函数的所有属性。(ps.你知道,slice()
必须知道一个已知的数组才能返回选定的元素的吧?但是这个已知的数组却没有作为参数传递给slice()
,这时slice()
要怎么才知道要从哪个已知数组返回元素?答案是在slice()
中使用this
拿到当前数组的所有元素。因为在Array()
肯定有一个或者多个属性,是保存着数组的所有元素的。)apply
是所有函数都具有的方法,就像所有
Array
都有slice
方法一样,只要在函数后加上.apply()
就能用了。这个方法的功能是调用函数,并且可以修改函数内的this
和传入函数的参数。先说说
apply()
的参数,有两个,第一个用于修改函数内的this
,第二个参数是数组,数组中的每个项都是传到调用apply()
的函数中的参数,相当于函数中的arguments。而
Array.prototype.slice()
中,this
是指Array()
,如果实例化过Array()
(var a = new Array();
)则是指a
,也就是一个数组。所以
Array.prototype.slice.apply(a,[])
等于a.slice()
。所以
Array.prototype.slice.apply([1]);
等于[1].slice()
等于var a=[1]; a.slice()
Array与object之间的关系
你会发现下面这个有趣的事情
其实数组是一个特殊的object对象,
[1,2]
约等于{0:1,1:2,length:2}
,这里是约等于哦,因为直接使用var a={0:1,1:2,length:2}
实例化的是Object,不是Array是不能用数组的专用方法的哦,如push
、slice
,会提示undefined is not a function
是找不到此方法的意思。但是此方法本身是可以处理这种格式的“数组”的,只是这个方法不在
Object
下,也不在Object.prototype
下而已,所以不能使用a.slice()
,所以才有了通过prototype
直接访问slice
方法,再使用apply
重新指向它的this,就可以使用slice
了。this
我以前也是不理解this是什么东西,好像在不同地方有不同的用法一样,但是现在发现,其实就只有一种用法,往细了来说,最多两种。
下面括号中的一段删除,因为我发现我错了,this的理解看来不是我想的那样,抱歉,但是用法是没错的
(this,可以把它看做是函数的一个隐藏参数、默认参数,默认情况下该参数等于此函数,即:
当this为默认值的时候,可以说它的功能就是给该函数添加属性,以及访问该函数的属性。)
而如果该函数是在其它函数(后面称为a函数)的
prototype
内,那this指的是a函数,也可以是该函数,也可以是其它a函数prototype
内的其它函数,因为这时候定义的属性在其它prototype
内的函数都能访问。那么问题来了,使用
jquery event
的时候,回调函数内的this
为什么指代的是触发事件的DOM
?实质上,只要使用apply()
,你可以把函数内的this
参数改为任何东西。最后再结合对象来说,一个函数可以看作是一个对象,this在默认情况下指的就是这个对象的意思,this在哪个对象内,指的就是哪个对象。所以可以给对象添加属性,方法。
楼上说得有点复杂了,我试着简单的说下:
slice的参数为(start, [.end]),start为必需
看再楼主的题目:
Array.prototype.slice.apply({0:1, length:1})
也就是说其实slice方法是没有传参数的
那么start就是undefined
slice方法中如果没有设置start,start就是0,可通过如下证明
[1,2].slice(); // [1,2]
end如果没有指定,就是当前对象的length属性的值,也就是1
那么结果就是{0:1}.slice(0, 1); // 这是伪代码哈
返回一个新的数组,从对象中0开始,到1结束,也就是取对象下标为0的值。
{0:1}[0] => 1;
所以返回[1]
如果这样写
Array.prototype.slice.apply({0:1, length:3})
结果就应该是
[1, undefined, undefined]
楼上几位回答很不错,但说的太细可能会让楼主略感迷茫...我来个简化版的
Array.prototype.slice
数组的切割方法,它返回的是一个被切割数组的副本,例如:
注意,它返回的是一个被切割的数组的副本。
apply
apply
和call
是把一个方法借给另外一个对象,最著名的就是类型判定:slice
是通用的,这个通用的是如何定义的呢?因为数组本身就是特殊的对象,那么数组的方法也可以借给一些和数组行为相似对象。当一个对象拥有和数组一样的特性,那么就可以使用
slice
。那么这个对象就拥有了和数组相似的特性,就可以使用
Array
的通用方法slice
。本质上,楼主的代码,实现的就是apply就是把数组的slice(),借给拥有和数组一样特性的对象。