Array.prototype.slice常见于两种调用场景:
一是对函数arguments对象的转换
Array.prototype.slice.call(arguments)
二是类似jquery原型对象的定义中
toArray: function() {
return slice.call( this, 0 );
},
有必要探究一番其使用方式和内部原理。
var objs = { "descType":function(o){ console.info(o); console.info("typeof o:" + (typeof o)); console.info("o.constructor:" + (o.constructor)); console.info("o instanceof Object:" + (o instanceof Object)); console.info("o instanceof Array:" + (o instanceof Array)); } };
var v = ['a',true,9].slice(0); objs.descType(v); VM1842:18 ["a", true, 9] VM1842:19 typeof o:object VM1842:20 o.constructor:function Array() { [native code] } VM1842:21 o instanceof Object:true VM1842:22 o instanceof Array:true
function f() { objs.descType(arguments); var newArg = Array.prototype.slice.call(arguments, 0); objs.descType(newArg); } f('aa','bb','cc'); VM1842:18 ["aa", "bb", "cc"] VM1842:19 typeof o:object VM1842:20 o.constructor:function Object() { [native code] } VM1842:21 o instanceof Object:true VM1842:22 o instanceof Array:false VM1842:18 ["aa", "bb", "cc"] VM1842:19 typeof o:object VM1842:20 o.constructor:function Array() { [native code] } VM1842:21 o instanceof Object:true VM1842:22 o instanceof Array:true
["aa", "bb", "cc"] 0:"aa" 1:"bb" 2:"cc" callee:function f() length:3
["aa", "bb", "cc"] 0:"aa" 1:"bb" 2:"cc" length:3
objs.descType(Array.prototype.slice.call(true,0)); objs.descType(Array.prototype.slice.call('abc',0)); objs.descType(Array.prototype.slice.call(256,0)); objs.descType(Array.prototype.slice.call({},0)); objs.descType(Array.prototype.slice.call(undefined,0)); objs.descType(Array.prototype.slice.call(null,0)); objs.descType(Array.prototype.slice.call(NaN,0));
objs.descType(Array.prototype.slice.call({'length':5},0));
objs.descType(Array.prototype.slice.call({'length':5,'0':'gebilaowang','1':'ximenqin'},0));
jQuery.prototype.init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); },
function slice(start, end) { var startToUse = start || 0, endToUse = end || ToUint32(this.length), result = []; for(var i = startToUse; i < endToUse; i++) { result.push(this[i]); } return result; }