// HANDLE: $(function)
// Process shorthand for DOM ready callback
} else if (jQuery.isFunction(selector)) {
// If selector is a function, treat it as $(document).ready()
return rootjQuery.ready(selector);
}
// Handle unusual syntax like $($('#div'))
if (selector.selector !== undefined) {
// Copy the selector string and context from the wrapped object
this.selector = selector.selector; // Equivalent to $($('#div')) -> $('#div')
this.context = selector.context;
}
return jQuery.makeArray(selector, this);
The code above is fairly straightforward as explained in comments. The key focus here is on jQuery.makeArray.
Behavior of $.makeArray
var e = null;
console.log($.makeArray(e)); // []
console.log($.makeArray({ a: 1, b: 2 })); // [{ a:1, b:2 }]
console.log($.makeArray({ '0': 1, '1': 2 })); // [{ '0':1, '1':2 }]
console.log($.makeArray({ '0': 1, '1': 2, 'a': '哈哈', length: 2 })); // [1, 2]
From these results:
- If the argument is
nullorundefined,$.makeArrayreturns an empty array[]. - If the argument is an object without a
lengthproperty, the entire object is treated as a single element in the resulting array. - If the object has a
lengthproperty, only numeric-like keys (from'0'tolength-1) are extracted; other keys are ignored. Iflengthis meaningless (e.g.,-1), the result may havelength: NaNand missing properties.
When a second argument is provided, $.makeArray merges the first argument into the second, but the second argument must have a length property (by default, an array). The merge behavior:
- Append the numeric properties of the first argument to the second argument's object.
- Update the total
lengthaccordingly. - If numeric keys overlap, the second argument's existing values take precedence (unless its
lengthis 0, in which case the first argument's values are used). - Non-numeric properties of the second argument remain untouched.
- The appended keys are determined by the final total
lengthafter merging.
console.log($.makeArray({'0':1,'1':2,'a':3,length:2},{length:1})); // {1: 1, 2: 2, length: 3}
console.log($.makeArray({'0':1,'1':2,'a':3,length:2},{'0':5,'1':8,'2':9,'a':'哈哈',length:2})); // {0:5,1:8,2:1,3:2,a:'哈哈',length:4}
Key difference from $.merge: $.merge only retains numeric properties based on the original length, while $.makeArray retains all properties from the second argument.
Returning from init
return jQuery.makeArray(selector, this);
This line is inside the init fnuction. The returned object is a jQuery object with numeric properties, a length property, and possibly other attributes like context. Earlier if blocks may return early, so this line acts as a fallback for other cases.
The init Function Recap
init returns a this object that contains native DOM nodes and a length property.
selector: '', // Default empty selector
length: 0, // Default length is 0
toArray: function() {
return core_slice.call(this); // core_slice = [].slice, converts the jQuery object to a real array
},
$(selector).toArray() converts a jQuery object into a native array. This is different from $.makeArray, which works on any object. toArray is primarily used internally by other methods, but it also supports the public API.
The get Method
get: function(num) {
return num == null
? this.toArray() // No argument: return a clean array
: num < 0
? this[this.length + num] // Negative index: count from end
: this[num]; // Non-negative: direct index
}
$(selector).get() without arguments is equivalent to $(selector).toArray(). With an argument:
$(selector).get(0)->$(selector).toArray()[0]$(selector).get(n)(n > 0) ->$(selector).toArray()[n]$(selector).get(n)(n < 0, e.g., -1 for last) ->$(selector).toArray()[length + n]
If num is not a number but exists as a property on the object, this[num] will return that property, though this is not a typical use case.