[].shift.call(arguments)
call
手写
Function.prototype.call = function (context) {
context = context ? Object(context) : window;
context.fn = this;
// 执行该函数
let args = [...arguments].slice(1);
let result = context.fn(...args);
// 删除该函数
delete context.fn;
// 注意:函数是可以有返回值的
return result;
};
shift
用法
shift
方法并不局限于数组:这个方法能够通过 call 或 apply 方法作用于类似数组的对象
上。但是对于没有 length 属性(从 0 开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
shift
普通调用
const array1 = [1, 2, 3];
const firstElement = array1.shift();
//shift 里面的this 是array1
相似的slice
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
Copy to Clipboard
除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。
/**
* Shim for "fixing" IE's lack of support (IE < 9) for applying slice
* on host objects like NamedNodeMap, NodeList, and HTMLCollection
* (technically, since host objects have been implementation-dependent,
* at least before ES2015, IE hasn't needed to work this way).
* Also works on strings, fixes IE < 9 to allow an explicit undefined
* for the 2nd argument (as in Firefox), and prevents errors when
* called on other DOM objects.
*/
(function () {
"use strict";
var _slice = Array.prototype.slice;
try {
// Can't be used with DOM elements in IE < 9
_slice.call(document.documentElement);
} catch (e) {
// Fails in IE < 9
// This will work for genuine arrays, array-like objects,
// NamedNodeMap (attributes, entities, notations),
// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
// and will not fail on other DOM objects (as do DOM elements in IE < 9)
Array.prototype.slice = function (begin, end) {
// IE < 9 gets unhappy with an undefined end argument
end = typeof end !== "undefined" ? end : this.length;
// For native Array objects, we use the native slice function
if (Object.prototype.toString.call(this) === "[object Array]") {
return _slice.call(this, begin, end);
}
// For array like object we handle it ourselves.
var i,
cloned = [],
size,
len = this.length;
// Handle negative value for "begin"
var start = begin || 0;
start = start >= 0 ? start : Math.max(0, len + start);
// Handle negative value for "end"
var upTo = typeof end == "number" ? Math.min(end, len) : len;
if (end < 0) {
upTo = len + end;
}
// Actual expected size of the slice
size = upTo - start;
if (size > 0) {
cloned = new Array(size);
if (this.charAt) {
for (i = 0; i < size; i++) {
cloned[i] = this.charAt(start + i);
}
} else {
for (i = 0; i < size; i++) {
cloned[i] = this[start + i];
}
}
}
return cloned;
};
}
})();
// ES5
var arg1 = Array.prototype.slice.call(arguments);
var arg2 = [].slice.call(arguments);
// ES6
var arg3 = Array.from(arguments);
var arg4 = [...arguments];
总结
slice
和shift
等 类似 api 对 内部this
的处理
this
- 是数组
- 是类数组
- xxx
function testErrorShift() {
return arguments.shift(); // arguments不是数组类型
}
testErrorShift();
// 改变内部this,达到数据的处理
function testshift() {
return [].shift.call(arguments);
}
console.log(testshift(1, 2, 3, 4, 5));
考察
- this 的指向
- 原生数组 api 对内部
this
的处理 this
的改变方法- 原型与原型链的考察
- 剩余运算符与扩展运算符
- 类数组