首先,有个单例对象,它上面挂了很多静态工具方法。其中有一个是each,用来遍历数组或对象。
var nativeForEach = [].forEach var nativeMap = [].map var util = { each: function (obj, iterator, context) { if (obj == null) return if (nativeForEach && obj.forEach === nativeForEach) { obj.forEach(iterator, context) } else if ( obj.length === +obj.length ) { for (var i = 0; i < obj.length; i++) { if (iterator.call(obj[i] || context, obj[i], i, obj) === true) return } } else { for (var k in obj) { if (iterator.call(obj[k] || context, obj[k], k, obj) === true) return } } }, map: function(obj, iterator, context) { var results = [] if (obj == null) return results if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context) this.each(obj, function(val, i, coll) { results[i] = iterator.call(context, val, i, coll) }) return results } }
还有诸如every、some等对集合(Array,Hash)操作的工具函数。使用时采用util.xx方式。
如果定义了一个集合类,这个类内部有集合数据。
function Collection(data) { this.data = data || [] // some other property // this.xxx = yyy } Collection.prototype = { // some method }
可以很方便的把util上的方法拷贝到集合类上,如
function copyMethod(clazz, obj) { for (var method in obj) { clazz.prototype[method] = function() { var args = [].slice.call(arguments) var target = this.data args.unshift(target) obj[method].apply(obj, args) } } } copyMethod(Collection, util)
这样拷贝后,Collection的实例就有了util上的方法,util操作的集合对象(第一个参数)就是Collection的this.data。如下直接可以遍历this.data了。
var coll = new Collection([10, 20, 30]) // 遍历 coll.each(function(k) { console.log(k) }) // 操作 var arr = coll.map(function(k) { return k - 5 }) console.log(arr) // 5, 15, 25
这种模式在很多开源库中使用,比如jQuery,它的 $.each/$.map 很方便的拷贝到了 $().each/$().map。
又如Backbone,它的 _.each/_.map/_.every/_.chain (还有很多)都拷贝到了 Collection的原型上。
// Underscore methods that we want to implement on the Collection. // 90% of the core usefulness of Backbone Collections is actually implemented // right here: var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle', 'lastIndexOf', 'isEmpty', 'chain']; // Mix in each Underscore method as a proxy to `Collection#models`. _.each(methods, function(method) { Collection.prototype[method] = function() { var args = slice.call(arguments); args.unshift(this.models); return _[method].apply(_, args); }; });
又有,把 _.keys / _.values / _.pairs / _.invert / _.pick 等对对象操作的实用方法拷贝了 Backbone.Model上 (1.0新增)
var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; // Mix in each Underscore method as a proxy to `Model#attributes`. _.each(modelMethods, function(method) { Model.prototype[method] = function() { var args = slice.call(arguments); args.unshift(this.attributes); return _[method].apply(_, args); }; });
相关推荐
总结来说,`apply`和`arguments`在JavaScript中提供了灵活的方法复用机制,允许我们改变函数的执行环境并处理动态参数。通过`apply`,我们可以将函数绑定到特定的对象上,同时传递任意数量的参数。`arguments`对象则...
继承允许子类继承父类的属性和方法,实现代码复用;多态则允许不同对象对同一消息做出不同的响应,增强了代码的灵活性。 总的来说,这个主题涵盖了JavaScript的高级特性和面向对象编程的核心概念,对于深入理解和...
在JavaScript中,每个函数都有`call()`和`apply()`这两个方法,它们都可以改变函数执行时的上下文,并传入参数。`apply()`的独特之处在于,它可以接受一个数组或类数组对象作为参数,将数组中的元素作为单独的参数...
在`Cat`构造函数中,`Animal.call(this, name)`将`Animal`的构造函数用`Cat`的`this`值调用,从而实现了属性和方法的继承。 ### 多重继承 JavaScript没有原生的多重继承,但可以通过`call`和`apply`模拟实现。例如...
总结,arguments对象提供了访问函数调用时所有参数的途径,caller属性提供了调用者的信息,callee属性指向当前执行的函数,apply方法允许动态设置函数调用的上下文和参数。理解和熟练使用这些特性,能够帮助开发者...
总结来说,`Array.prototype.slice.apply` 是一种在JavaScript中将 `arguments` 对象或类似数组对象转换为真正数组的实用技巧,允许我们利用数组的方法进行操作。尽管有其他库提供类似功能,但直接使用 `apply` 可以...
在JavaScript中,`apply`和`call`方法都是Function对象的内置方法,它们的主要作用是改变函数调用时的上下文(即`this`值),并允许我们在不同对象上执行同一方法,从而实现方法的借用。这两者在功能上相似,但参数...
`arguments`对象的属性和方法主要有: 1. **length属性**:`arguments.length`返回函数被调用时传入的参数个数,这与函数定义中的形参数量可能不同。 2. **索引访问**:可以通过索引来访问`arguments`对象中的参数...
在某些场景下,我们希望将函数绑定到特定对象上,但不希望硬编码对象和方法的关系。`apply()`可以做到这一点: ```javascript function sayColor() { console.log(this.color); } var o = {color: 'blue'}; ...
"arguments-extended"就是一个这样的开源库,专为处理JavaScript中的`arguments`对象提供了一系列实用方法,旨在增强参数操作的灵活性和便利性。 `arguments`对象在JavaScript中是一个特殊的对象,它在函数内部可用...
### 理解JavaScript中的`caller`...综上所述,理解`caller`、`callee`、`call`、`apply`以及`arguments`对象在JavaScript编程中至关重要,它们不仅增强了函数的灵活性和复用性,还提供了深入分析和调试代码的强大工具。
一、call和apply的说明 1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为...
`arguments`对象是一个类数组对象,意味着它拥有索引(从0开始)和`length`属性,但它并不具备数组的所有方法,如`push`、`pop`等。当你在一个函数内部访问`arguments`时,你可以通过索引访问传递给该函数的所有参数...
在示例中,`Person`类通过`Person.apply(this, arguments)`使得`Student`类继承了`Person`类的所有属性和方法。`apply`的第一个参数`this`被替换为新创建的`Student`实例,第二个参数`arguments`是一个数组,代表...
在JavaScript中,函数的形式参数和arguments之间存在着微妙的关系。为了深入理解这方面的知识,我们需要首先了解形式参数和实际参数的概念。形式参数指的是定义方法时所明确指定的参数,而实际参数则是指javascript...
JavaScript中的`arguments`对象是一个...通过`arguments.length`可以获取参数个数,通过索引访问参数值,以及利用`arguments.callee`实现递归等功能。在编写函数时,善用`arguments`可以使代码更具灵活性和可扩展性。
JavaScript中的call、apply和bind方法都是用来改变函数调用时的上下文(即this值)以及传递参数。它们之间的相同点在于,都能够指定函数执行时的this对象,并且都能接收参数。不同点在于它们的调用方式和执行时机。 ...