为JavaScript添加重载函数的提携方法,对象详解

JavaScript arguments 对象详解

2016/10/24 · JavaScript
· arguments

原稿出处:
CompileYouth   

1. 什么样是类数组

  arguments
是一个类数组对象。代表传给一个function的参数列表。

   我们来传一个实例。

 function printArgs() {

     console.log(arguments);

   }

   printArgs(“A”, “a”, 0, { foo: “Hello, arguments” });

 // [“A”, “a”, 0, Object]

 再看看 arguments
表示的情节,其象征了函数执行时传出函数的所有参数。在地点的例证中,代表了流传
printArgs 函数中的多个参数,可以分别用
arguments[0]、 arguments[1]… 来获取单个的参数

 

JavaScript的重载函数,一般是靠对arguments判断来操作的。
比如:

JavaScript函数具有像数组一样的靶子,那一个目的称为arguments,与传递给函数的参数相呼应。传递给JavaScript函数的保有参数都得以应用arguments对象来引用。

1. 什么是 arguments

MDN
上解释:

arguments 是一个类数组对象。代表传给一个function的参数列表。

俺们先用一个例子直观通晓下 JavaScript 中的 arguments 长什么体统。

JavaScript

function printArgs() { console.log(arguments); } printArgs(“A”, “a”, 0,
{ foo: “Hello, arguments” });

1
2
3
4
5
function printArgs() {
    console.log(arguments);
}
 
printArgs("A", "a", 0, { foo: "Hello, arguments" });

实践结果是:

JavaScript

[“A”, “a”, 0, Object]

1
["A", "a", 0, Object]

乍一看,结果是个数组,但并不是确实的数组,所以说 arguments
是一个类数组的靶子(想驾驭真正数组与类数组对象的界别可以一贯翻到终极)。

再看看 arguments
表示的情节,其象征了函数执行时传出函数的有所参数。在地点的例证中,代表了流传
printArgs 函数中的多少个参数,可以分级用 arguments[0]
arguments[1]… 来得到单个的参数。

2. arguments 的操作

 arguments.length

    arguments
是个类数组对象,其蕴藉一个 length 属性,可以用 arguments.length
来得到传播函数的参数个数。

   arguments 转数组

   
Array.prototype.silce.call(arguments);  // 或者选用 [].slice.call(arguments);

   修改 arguments
值。

  function foo(a) {

      ”use strict”;

      console.log(a, arguments[0]);

      a = 10;

      console.log(a, arguments[0]);

      arguments[0] = 20;

      console.log(a, arguments[0]);

  }

  foo(1);

  // 1 1    //10 1    //10 20

  非严谨情势的事例:

  function foo(a) {

 

      console.log(a, arguments[0]);

 

      a = 10;

 

      console.log(a, arguments[0]);

 

      arguments[0] = 20;

 

      console.log(a, arguments[0]);

 

  }

 

  foo(1);

  // 1 1    //10 10     //20 20

  在严刻方式下,函数中的参数与 arguments
对象没有交换,修改一个值不会转移另一个值。而在非严厉格局下,七个会相互影响。

 

复制代码 代码如下:

 

亚洲必赢官网,2. arguments 操作

3.  数组与类数组对象

  数组具有一个基本特征:索引。那是相似对象所未曾的。

const obj = { 0: “a”, 1: “b” };

const arr = [ “a”, “b” ];

  大家拔取 obj[0]、arr[0]
都能获得自己想要的多寡,但收获数据的不二法门确实今非昔比的。obj[0]
是利用目标的键值对存取数据,而arr[0]
却是利用数组的目录。事实上,Object 与 Array 的唯一分化就是 Object
的属性是 string,而   Array 的目录是 number。

  上面看看类数组对象。

  伪数组的风味就是长得像数组,包涵一组数据以及所有一个
length 属性,可是从未其余 Array 的点子。再具体的说,length
属性是个非负整数,上限是 JavaScript
中能精确表明的最大数字;其余,类数组对象的 length
值不能自行改变。

  亚洲必赢官网 1

var afunc = function() {
args = arguments;
if(args.length == 1) {
console.log(1);
}else if(args.length == 2) {
console.log(2);
为JavaScript添加重载函数的提携方法,对象详解。}else if (args.length == 3) {
console.log(3);
}
}

当今我们发轫学习,仔细看上面列出的代码:

2.1 arguments length

arguments 是个类数组对象,其蕴藉一个 length 属性,可以用
arguments.length 来得到传播函数的参数个数。

JavaScript

function func() { console.log(“The number of parameters is ” +
arguments.length); } func(); func(1, 2); func(1, 2, 3);

1
2
3
4
5
6
7
function func() {
    console.log("The number of parameters is " + arguments.length);
}
 
func();
func(1, 2);
func(1, 2, 3);

实施结果如下:

JavaScript

The number of parameters is 0 The number of parameters is 2 The number
of parameters is 3

1
2
3
The number of parameters is 0
The number of parameters is 2
The number of parameters is 3

可以想象假若重载数量多的时候,要有些许的if-else判断啊(事实上重载数量应该不会皇太后多啊)。
设若要对js函数举行重载,代码量肯定是多的。那么能仍然不能够想方法使代码清晰点,再收缩那个一样代码的书写呢?
那就是自身写篇小说和血脉相通代码的缘起了。
惯例先上代码:

 

2.2 arguments 转数组

常见采用下边的格局来将 arguments 转换成数组:

JavaScript

Array.prototype.slice.call(arguments);

1
Array.prototype.slice.call(arguments);

再有一个更简约的写法:

JavaScript

[].slice.call(arguments);

1
[].slice.call(arguments);

在那里,只是不难地调用了空数组的 slice 方法,而从未从 Array
的原型层面调用。

干什么上边三种形式可以转移呢?

先是,slice 方法赢得的结果是一个数组,参数便是
arguments。事实上,满意一定条件的目标都能被 slice
方法转换成数组。看个例子:

JavaScript

const obj = { 0: “A”, 1: “B”, length: 2 }; const result =
[].slice.call(obj); console.log(Array.isArray(result), result);

1
2
3
const obj = { 0: "A", 1: "B", length: 2 };
const result = [].slice.call(obj);
console.log(Array.isArray(result), result);

执行结果是:

JavaScript

true [“A”, “B”]

1
true ["A", "B"]

从上面例子可以见见,条件就是: 1) 属性为 0,1,2…;2) 具有 length
属性;

别的,有一个亟待小心的地点就是,不能将函数的 arguments
走漏或者传递出去
。什么意思呢?看下边的多少个走漏 arguments 的例子:

JavaScript

// Leaking arguments example1: function getArgs() { return arguments; }
// Leaking arguments example2: function getArgs() { const args =
[].slice.call(arguments); return args; } // Leaking arguments
example3: function getArgs() { const args = arguments; return function()
{ return args; }; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Leaking arguments example1:
function getArgs() {
    return arguments;
}
 
// Leaking arguments example2:
function getArgs() {
    const args = [].slice.call(arguments);
    return args;
}
 
// Leaking arguments example3:
function getArgs() {
    const args = arguments;
    return function() {
        return args;
    };
}

上面的做法就径直将函数的 arguments 对象泄表露去了,最后的结果就是 V8
引擎将会跳过优化,导致极度大的性质损失。

您能够那样做:

JavaScript

function getArgs() { const args = new Array(arguments.length); for(let i
= 0; i < args.length; ++i) { args[i] = arguments[i]; } return
args; }

1
2
3
4
5
6
7
function getArgs() {
    const args = new Array(arguments.length);
    for(let i = 0; i < args.length; ++i) {
        args[i] = arguments[i];
    }
    return args;
}

那就很好奇了,我们每一次使用 arguments
时一般第一步都会将其更换为数组,同时 arguments
使用不当还简单造成性能损失,那么为什么不将 arguments
直接设计成数组对象啊?

那亟需从那门语言的一上马说起。arguments 在语言的早期就引入了,当时的
Array 对象具备 4 个措施: toString、 join、 reverse 和 sort。arguments
继承于 Object 的很大原因是不须要那七个情势。而近来,Array
添加了好多强大的格局,比如 forEach、map、filter
等等。这怎么现在不在新的版本里让 arguments 重新继承自 Array呢?其实
ES5 的草案中就富含那或多或少,但为了向前包容,最后仍然被委员会否决了。

复制代码 代码如下:

function add(num1, num2) {

    var res = num1 + num2;

    return res;

}

var r = add(7, 8);

console.log(r);

2.3 修改 arguments 值

在严厉情势与非严酷格局下,修改函数参数值表现的结果不雷同。看上边的七个例子:

JavaScript

function foo(a) { “use strict”; console.log(a, arguments[0]); a = 10;
console.log(a, arguments[0]); arguments[0] = 20; console.log(a,
arguments[0]); } foo(1);

1
2
3
4
5
6
7
8
9
function foo(a) {
    "use strict";
    console.log(a, arguments[0]);
    a = 10;
    console.log(a, arguments[0]);
    arguments[0] = 20;
    console.log(a, arguments[0]);
}
foo(1);

输出:

JavaScript

1 1 10 1 10 20

1
2
3
1 1
10 1
10 20

另一个非严谨格局的例证:

JavaScript

function foo(a) { console.log(a, arguments[0]); a = 10; console.log(a,
arguments[0]); arguments[0] = 20; console.log(a, arguments[0]); }
foo(1);

1
2
3
4
5
6
7
8
function foo(a) {
    console.log(a, arguments[0]);
    a = 10;
    console.log(a, arguments[0]);
    arguments[0] = 20;
    console.log(a, arguments[0]);
}
foo(1);

输出结果为:

JavaScript

1 1 10 10 20 20

1
2
3
1 1
10 10
20 20

从地方的八个例证中可以见见,在严谨方式下,函数中的参数与 arguments
对象没有关系,修改一个值不会变动另一个值。而在非严酷情势下,多个会相互影响。

/** KOverLoad
一个成立重载函数的救助方法。
实在那么些办法只是扶助打点了参数不一样的情状下的重载方法。
一旦还要对参数类型进行判断重载的话,请在提供的情势中温馨完结。
@Author ake 2010-05-02
@weblog
*/
var KOverLoad = function(scope) {
this.scope = scope || window;
//默认添加方法到这么些目的中。同时加上的点子的this指向该对象。
this.list = {}; //存放重载函数的地点。
return this;
};
KOverLoad.prototype = {
//添加一个重载的艺术。
//@param arg<Function> 重载的方式。
add:function(arg) {
if(typeof arg == “function”) {
this.list[arg.length] = arg;
//以参数数量做标识存储重载方法。很明确假使您的重载方法参数数量
}
return this;
},
//添加完所有的重载函数未来,调用该方法来创立重载函数。
//@param fc<String> 重载函数的艺术名。
load:function(fc) {
var self = this, args, len;
this.scope[fc] = function() { //将指定效能域的指定方法
设为重载函数。
args = Array.prototype.slice.call(arguments, 0); //将参数转换为数组。
len = args.length;
if(self.list[len]) { //根据参数数量调用符合的重载方法。
self.list[len].apply(self.scope, args); //那里指定了功能域和参数。
}else{
throw new Error(“undefined overload type”);
}
}
}
};

 

2.4 将参数从一个函数传递到另一个函数

上边是将参数从一个函数传递到另一个函数的推介做法。

JavaScript

function foo() { bar.apply(this, arguments); } function bar(a, b, c) {
// logic }

1
2
3
4
5
6
function foo() {
    bar.apply(this, arguments);
}
function bar(a, b, c) {
    // logic
}

运用 方法是本身以为相比较清楚的主意:
//那是可选的机能对象。

在地方的函数中,num1和num2是三个参数。你可以运用名为num1和num2的arguments来引用这一个参数。除了arguments名称之外,你还能动用JavaScript数组,如目的arguments来引用它们。所以,上边的函数可以重写,如下所示:

2.5 arguments 与重载

许多语言中都有重载,但 JavaScript 中从不。先看个例证:

JavaScript

function add(num1, num2) { console.log(“Method one”); return num1 +
num2; } function add(num1, num2, num3) { console.log(“Method two”);
return num1 + num2 + num3; } add(1, 2); add(1, 2, 3);

1
2
3
4
5
6
7
8
9
10
11
12
function add(num1, num2) {
    console.log("Method one");
    return num1 + num2;
}
 
function add(num1, num2, num3) {
    console.log("Method two");
    return num1 + num2 + num3;
}
 
add(1, 2);
add(1, 2, 3);

执行结果为:

JavaScript

Method two Method two

1
2
Method two
Method two

所以,JavaScript 中,函数并从未按照参数的两样而暴发分歧的调用。

是否 JavaScript 中就从未重载了吗?并不是,大家可以运用 arguments
模拟重载。依旧地方的例证。

JavaScript

function add(num1, num2, num3) { if (arguments.length === 2) {
console.log(“Result is ” + (num1 + num2)); } else if (arguments.length
=== 3) { console.log(“Result is ” + (num1 + num2 + num3)); } } add(1,
2); add(1, 2, 3)

1
2
3
4
5
6
7
8
9
10
11
function add(num1, num2, num3) {
    if (arguments.length === 2) {
        console.log("Result is " + (num1 + num2));
    }
    else if (arguments.length === 3) {
        console.log("Result is " + (num1 + num2 + num3));
    }
}
 
add(1, 2);
add(1, 2, 3)

实践结果如下:

JavaScript

Result is 3 Result is 6

1
2
Result is 3
Result is 6

复制代码 代码如下:

 

3. ES6 中的 arguments

var s =function(){}
s.prototype = {
init:function() {
console.log();
}
}

function add(num1, num2) {

    var res = arguments[0] + arguments[1];

    return res;

}

var r = add(7, 8);

console.log(r);

3.1 增加操作符

直白上栗子:

JavaScript

function func() { console.log(…arguments); } func(1, 2, 3);

1
2
3
4
5
function func() {
    console.log(…arguments);
}
 
func(1, 2, 3);

施行结果是:

JavaScript

1 2 3

1
1 2 3

简单地讲,增加操作符可以将 arguments 展开成单身的参数。

//构造函数的参数可以是Object类型的如故其余合法的品类,若是不点名,则注册到window对象中,并且效用域也是window。其实就是添加该重载方法到怎么着地方而已。

 

3.2 Rest 参数

或者上栗子:

JavaScript

function func(firstArg, …restArgs) {
console.log(Array.isArray(restArgs)); console.log(firstArg, restArgs); }
func(1, 2, 3);

1
2
3
4
5
6
function func(firstArg, …restArgs) {
    console.log(Array.isArray(restArgs));
    console.log(firstArg, restArgs);
}
 
func(1, 2, 3);

施行结果是:

JavaScript

true 1 [2, 3]

1
2
true
1 [2, 3]

从下面的结果可以见见,Rest 参数表示除了众所周知指定剩下的参数集合,类型是
Array。

复制代码 代码如下:

在JavaScript函数中,arguments对象用于访问或引用传递给函数的拥有参数。arguments对象是可用于函数的一部分变量。arguments对象的长短约等于传递给函数的arguments数量。请看上面的代码,作为出口将赢得2,因为有四个arguments传递给函数:

3.3 默认参数

栗子:

JavaScript

function func(firstArg = 0, secondArg = 1) { console.log(arguments[0],
arguments[1]); console.log(firstArg, secondArg); } func(99);

1
2
3
4
5
6
function func(firstArg = 0, secondArg = 1) {
    console.log(arguments[0], arguments[1]);
    console.log(firstArg, secondArg);
}
 
func(99);

举办结果是:

JavaScript

99 undefined 99 1

1
2
99 undefined
99 1

足见,默许参数对 arguments 没有影响,arguments
依然只是意味着调用函数时所盛传的兼具参数。

new KOverLoad(s.prototype).add(function(a) {
console.log(“one”,a,this)
})
 .add(function(a,b) {
console.log(“two”,a,b,this)
})
 .add(function(a,b,c) {
console.log(“three”,a,b,c,this)
})
 .add(function(a,b,c,d) {
console.log(“four”,a,b,c,d,this)
})
 .load(“func”); //在那边的参数就是要开创的重载函数的艺术名称。

 

3.4 arguments 转数组

Array.from() 是个极度推荐的方法,其得以将所有类数组对象转换成数组。

达成上述操作之后,s.func就是一个重载函数。
咱俩可以那样调用重载函数:

function add(num1, num2) {

    var res = arguments.length;

    return res;

}

var r = add(7, 8);

console.log(r);

4. 数组与类数组对象

数组具有一个基本特征:索引。这是形似对象所没有的。

JavaScript

const obj = { 0: “a”, 1: “b” }; const arr = [ “a”, “b” ];

1
2
const obj = { 0: "a", 1: "b" };
const arr = [ "a", "b" ];

俺们使用 obj[0]arr[0]
都能赢得自己想要的多少,但获得数据的主意实在今非昔比的。obj[0]
是利用目的的键值对存取数据,而arr[0]
却是利用数组的目录。事实上,Object 与 Array 的绝无仅有分歧就是 Object
的习性是 string,而 Array 的目录是 number。

下边看看类数组对象。

伪数组的特色就是长得像数组,蕴涵一组数据以及有着一个 length
属性,但是并未任何 Array 的艺术。再具体的说,length
属性是个非负整数,上限是 JavaScript
中能精确表明的最大数字;其它,类数组对象的 length 值不可以自行改变。

怎么团结创制一个类数组对象?

JavaScript

function Foo() {} Foo.prototype = Object.create(Array.prototype); const
foo = new Foo(); foo.push(‘A’); console.log(foo, foo.length);
console.log(“foo is an array? ” + Array.isArray(foo));

1
2
3
4
5
6
7
function Foo() {}
Foo.prototype = Object.create(Array.prototype);
 
const foo = new Foo();
foo.push(‘A’);
console.log(foo, foo.length);
console.log("foo is an array? " + Array.isArray(foo));

实践结果是:

JavaScript

[“A”] 1 foo is an array? false

1
2
["A"] 1
foo is an array? false

也就是说 Foo 的以身作则拥有 Array 的有着办法,但项目不是 Array。

若果不须求 Array 的拥有办法,只需求有些如何做吧?

JavaScript

function Bar() {} Bar.prototype.push = Array.prototype.push; const bar =
new Bar(); bar.push(‘A’); bar.push(‘B’); console.log(bar);

1
2
3
4
5
6
7
function Bar() {}
Bar.prototype.push = Array.prototype.push;
 
const bar = new Bar();
bar.push(‘A’);
bar.push(‘B’);
console.log(bar);

实践结果是:

JavaScript

Bar {0: “A”, 1: “B”, length: 2}

1
Bar {0: "A", 1: "B", length: 2}

参考:

  1. JavaScript中的数组与伪数组的区分
  2. MDN
    arguments
  3. Avoid modifying or passing arguments into other functions — it
    kills
    optimization
  4. Optimization
    killers
  5. Why isn’t a function’s arguments object an array in
    Javascript?
  6. arguments
    对象
  7. Advanced Javascript: Objects, Arrays, and Array-Like
    objects
  8. JavaScript 特殊对象 Array-Like Objects
    详解
  9. What is a good way create a Javascript array-like
    object?

    1 赞 3 收藏
    评论

亚洲必赢官网 2

复制代码 代码如下:

 

var t = new s();
t.func();//抛出荒唐相当。因为从没点名零参数时的函数
t.func(”o”);//one o Object {}
t.func(1,2);//two 1 2 Object {}

arguments对象不是纯数组

简简单单的代码而已,假设各位有指出仍旧意见,欢迎留言指教。

 

您或许感兴趣的小说:

  • JS重载已毕方式分析
  • JS模拟已毕格局重载示例
  • JavaScript中的方法重载实例
  • javascript中通过arguments参数伪装方法重载
  • js面向对象编程之怎么着促成格局重载
  • js中艺术重载如何兑现?以及函数的参数问题
  • 有关于JS构造函数的重载和工厂方法
  • 添加JavaScript重载函数的增援方法2
  • JavaScript 的方法重载效果
  • 妙用缓存调用链达成JS方法的重载

JavaScript的arguments对象不是彻头彻尾的JavaScript数组。你不能对arguments对象举行诸如push,pop,slice等操作。正如你将在底下列出的代码中所看到的那么,执行push操作会吸引那一个,因为arguments.push不是函数。

 

function add(num1, num2) {

    arguments.push(78);

    var res = num1 + num2;

    return res;

}

 

可以设置arguments对象

 

您能够在arguments对象数组中设置一定的项。首先,你可以使用索引0设置数组的首先个项,如下所示:

 

function add(num1, num2) {

    arguments[0] = 15;

    var res = num1 + num2;

    return res;

}

var r = add(7, 8);

console.log(r);

 

在add函数中,num1和arguments[0]引用相同的值。所以,当你更新arguments[0]时,num1的值也会被更新。对于地方的代码,输出将是23。

 

将arguments对象转换为数组

 

正如大家在那篇小说中介绍的那么,JavaScript函数arguments对象不是纯数组。除了长度属性外,它没有其余其余属性。不过,你可以应用Array.prototype.slice.call将arguments对象转换为数组,如下所示:

 

function add(num1, num2) {

    var arg = Array.prototype.slice.call(arguments);

    console.log(arg.pop());

}

 

在ECMAScript 6中,你可以将arguments对象转换为一个数组,如下所示:

 

function add(num1, num2) {

    var arg = Array.from(arguments);

    console.log(arg.pop());

}

 

结论

 

简单的说,关于arguments对象急需谨记的有些根本业务有:

 

  • arguments对象的长度等于传递给函数的参数的数额。

  • arguments对象是类似数组的对象,但不是JavaScript数组。

  • 您无法对arguments对象使用别的JavaScript数组方法,例如push,pop,slice等等。

  • JavaScript
    arguments对象索引从零开端。所以首先个参数将被arguments[0]引用,第四个参数将被arguments[1]引用,等等。

 

简易地说,JavaScript
arguments对象是一个类似数组的目的,它引用传递给函数的参数。在ECMAScript
6中,引入的rest参数现已被普遍用来代替函数中的arguments对象用于变量数或参数。

 

网站地图xml地图