如何引用Array.prototype.slice.call()?

发布于 2024-11-26 20:15:52 字数 473 浏览 4 评论 0原文

我正在编写一个脚本,其中需要在许多不同的地方克隆数组。因此,我想执行以下操作来模拟克隆函数:

var clone = [].slice.call;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone(arr1, 0);

不幸的是,上面的代码导致:TypeError: object is not a function。我意识到有很多函数可以进行深度克隆和浅层复制,但我只想使用内置方法。有趣的是,以下内容确实有效:

var clone = [].slice;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone.call(arr1, 0);

有谁知道为什么第一个块不起作用而第二个块起作用?有没有什么方法可以引用函数调用并应用函数,而不会在调用引用的函数时抛出错误?

I am writing a script in which I need to clone arrays in many different places. For this reason, I would like to do the following to emulate a cloning function:

var clone = [].slice.call;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone(arr1, 0);

Unfortunately, the above code results in: TypeError: object is not a function. I realize there are many functions out there to do deep cloning and shallow copies but I just want to use the built in method. Interestingly enough, the following does work:

var clone = [].slice;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone.call(arr1, 0);

Does anyone know why the first block doesn't work while the second does? Is there any way to reference a functions call and apply functions without throwing errors when calling the referenced function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

江湖彼岸 2024-12-03 20:15:52

我必须绝对同意 Felix King 和 pimvdb 的观点。我认为使用 Function.protoytpe.bind() 函数的唯一缺点是,这不是一个在所有浏览器(例如 IE6)中都可用的函数。另一种方法是使用提供 curry() 函数的 JavaScript 库。另一种选择是定义一个函数,使您能够检索任何其他函数的调用函数。这是我发布在我的博客上的定义对于这样一个我称之为 getCall() 的函数:

Function.prototype.getCall = function() {
  var realFn = this;
  return function(objThis) {
    return realFn.apply(objThis, Array.prototype.slice.call(arguments, 1));
  };
};

现在,通过这个定义,您可以执行以下操作来获取对切片函数的调用函数的引用:

var slice = [].slice.getCall();

I have to definitely agree with both Felix King and pimvdb. I think the only drawback to using the Function.protoytpe.bind() function is the fact that this is not a function that is available in all browsers (IE6 for example). An alternative would be to use a JavaScript library that provides the curry() function. Another alternative would be to define a function which gives you the ability to retrieve the call function for any other function. Here is a definition that I posted on my blog for such a function which I called getCall():

Function.prototype.getCall = function() {
  var realFn = this;
  return function(objThis) {
    return realFn.apply(objThis, Array.prototype.slice.call(arguments, 1));
  };
};

Now, with this definition, you could do the following to get a reference to the call function of the slice function:

var slice = [].slice.getCall();
吃不饱 2024-12-03 20:15:52

您可以通过直接调用 slice 来克隆数组:

var arr2 = arr1.slice();

如果您想要一个 clone 函数,您可以这样做:

var clone = function(arr) { return arr.slice(); };

如果您确实想要原型函数(只要函数不会被覆盖):

var clone = function(arr) { return [].slice.call(arr); };

为什么不能直接引用 callapply

与分配方法的原因相同,它不起作用对象到变量的转换不起作用。

如果您调用 func.call(),则 call 内的 this 将是对 func(一个函数对象)的引用。

如果将 call 分配给变量,则上下文将丢失。您有对通用 call 函数的引用。因此,您必须再次将正确的上下文(您想要应用 call 的方法)作为第一个参数传递给 call

var clone = [].slice.call;
var arr2 = clone.call([].slice, arr1);

这并不是真正的改进,而且相当令人困惑。

callapply 是每个函数都继承自 Function.prototype 的方法。函数没有自己的版本。 [].slice.call === [].splice.call 产生 true

You can clone an array by calling slice directly:

var arr2 = arr1.slice();

If you want a clone function, you can do:

var clone = function(arr) { return arr.slice(); };

If you really want to prototype function (which is not necessary as long as the function is not overwritten):

var clone = function(arr) { return [].slice.call(arr); };

Why can't you reference call or apply directly?

It does not work for the same reason assigning a method of an object to a variable does not "work".

If you call func.call() then this inside call will be a reference to func, a function object.

If you assign call to a variable then the context is lost. You have a reference to the generic call function. Thus you'd have to pass the correct context (the method you want to apply call to) as first parameter to call again:

var clone = [].slice.call;
var arr2 = clone.call([].slice, arr1);

This is not really an improvement and quite confusing.

call and apply are methods that every functions inherits from Function.prototype. Functions don't have their own version of them. [].slice.call === [].splice.call yields true.

北风几吹夏 2024-12-03 20:15:52

区别在于函数的范围,即“this”是什么。我不确定正确的技术术语是什么,但是当函数被称为“独立”或作为对象的属性时,“this”是不同的。

var myObj = {};
myObj.foo = function () {
    console.log(this.bar);
};
myObj.bar = 1234;

var fooRef = myObj.foo;

myObj.foo(); // 1234
fooRef(); // undefined

但是,您可以创建一个函数来包装对该函数的调用并传递所有参数:

var fooEncapsulated = function () {
    return myObj.foo.apply(myObj, arguments);
}

fooEncapsulated(); // 1234

根据记录,最常见的方法是:

Array.prototype.slice.call(myArray, other, arguments, here);

The difference is the scope of the function, i.e. what "this" is. I'm not sure what the correct technical terms are, but the "this" is not the same when a function is called "stand alone" or as a property of an object.

var myObj = {};
myObj.foo = function () {
    console.log(this.bar);
};
myObj.bar = 1234;

var fooRef = myObj.foo;

myObj.foo(); // 1234
fooRef(); // undefined

You can however create a function that wraps a call to the function and passes on all the arguments:

var fooEncapsulated = function () {
    return myObj.foo.apply(myObj, arguments);
}

fooEncapsulated(); // 1234

For the record, the most common way of doing this is:

Array.prototype.slice.call(myArray, other, arguments, here);
为你拒绝所有暧昧 2024-12-03 20:15:52

问题是 whatever_function.call 等于 Function.prototype.call。因此,您有效地保存了对 Function.prototype.call 的引用,并且它是切片函数的信息丢失了。

将其与自定义函数进行比较:

Function.prototype.custom = function() { console.log(this) };

[].slice.custom(); // logs slice function

var ref = [].slice.custom;
ref(); // logs window object

防止 this 值被更改的方法是使用 Function.prototype.bind

var ref = [].slice.call.bind([].slice);

现在,

ref([1,2,3], 1); // [2, 3]

因为在调用 .call 时 函数中,this 值绑定到切片函数,一切都按预期工作。

The problem is that whatever_function.call is equal to Function.prototype.call. Thus, you effectively save a reference to Function.prototype.call and the information that it is the slice function is lost.

Compare it with a custom function:

Function.prototype.custom = function() { console.log(this) };

[].slice.custom(); // logs slice function

var ref = [].slice.custom;
ref(); // logs window object

A method of keeping the this value from being changed is using Function.prototype.bind:

var ref = [].slice.call.bind([].slice);

Now,

ref([1,2,3], 1); // [2, 3]

because when calling the .call function, the this value is bound to the slice function and everything works as expected.

眉目亦如画i 2024-12-03 20:15:52

甜蜜又简单:

slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1,2,3]); // [1,2,3]
slice({length:3,0:1,1:2,2:3}); // [1,2,3]

Sweet and simple:

slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1,2,3]); // [1,2,3]
slice({length:3,0:1,1:2,2:3}); // [1,2,3]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文