Secrets of the Javascript Ninja (Understanding function invocation)

JS忍者秘籍(理解函数调用)

隐式参数

The arguments parameter is a collection of all arguments passed to a function. It’s useful because it allows us to access all function arguments, regardless of whether the matching parameter is explicitly defined.

arguments 是关于函数参数的一个集合,通过argument我们可以获取函数的所有参数,无论这些参数是否被显示的定义。

function whatever(a, b, c){
assert(a === 1, 'The value of a is 1');
assert(b === 2, 'The value of b is 2');
assert(c === 3, 'The value of c is 3');
assert(arguments.length === 5,
'We’ve passed in 5 parameters');
assert(arguments[0] === a,
'The first argument is assigned to a');
assert(arguments[1] === b,
'The second argument is assigned to b');
assert(arguments[2] === c,
'The third argument is assigned to c');
assert(arguments[3] === 4,
'We can access the fourth argument');
assert(arguments[4] === 5,
'We can access the fifth argument');
}
whatever(1,2,3,4,5);

以上例子可以看出,arguments中包含了所有传入的参数,尽管这些参数中有的没有被显式的声明。

function sum() {
var sum = 0;
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
return sum;
}
assert(sum(1, 2) === 3, "We can add two numbers");
assert(sum(1, 2, 3) === 6, "We can add three numbers");
assert(sum(1, 2, 3, 4) === 10, "We can add four numbers");

我们可以对这些参数进行遍历。
但当我们处于严格模式下时,有一些不同之处:

"use strict";
function infiltrate(person){
assert(person === 'gardener',
'The person is a gardener');
assert(arguments[0] === 'gardener',
'The first argument is a gardener');
arguments[0] = 'ninja';
assert(arguments[0] === 'ninja',
'The first argument is now a ninja');
assert(person === 'gardener',
'The person is still a gardener');
}
infiltrate("gardener");

当我们通过arguments改变了参数的值,但是却只是改变了arguments中的参数,显式的参数依然是传入时的值。因此我们可以认为arguments只是一种强引用。

函数上下文

When a function is invoked, in addition to the parameters that represent the explicit arguments provided in the function call, an implicit parameter named this is passed to the function. The this parameter, a vital ingredient in object-oriented JavaScript, refers to an object that’s associated with the function invocation. For this reason, it’s often termed the function context.

当一个函数被调用时,所有的显示参数就会被唤起,而隐式参数则需要通过this来传递,在JS面向对象中,this扮演着至关重要的角色。

函数调用的几种方式:

1、作为函数调用

function ninja(){};
ninja();
var samurai = function(){};
samurai(); 
(function(){})() //立即执行函数(IIFE)

函数的三种常规调用。在严格模式下函数内部的this上下文为undefined,非严格模式下this指向window
2、作为方法调用

var ninja = {};
ninja.skulk = function(){};
ninja.skulk();

将函数赋值对象中的变量,并作为一个方法保存在对象内部。
以上两种调用的区别就在于:

function whatsMyContext() {
return this;
}
assert(whatsMyContext() === window,
"Function call on window");
var getMyThis = whatsMyContext;
assert(getMyThis() === window,
"Another function call in window");
var ninja1 = {
getMyThis: whatsMyContext
};
assert(ninja1.getMyThis() === ninja1,
"Working with 1st ninja");
var ninja2 = {
getMyThis: whatsMyContext
};
assert(ninja2.getMyThis() === ninja2,
"Working with 2nd ninja");

当我们利用常规调用函数时,断言函数会打印出函数内部的this指向了全局变量window,换句话说this可以访问全局变量,当作为对象中的方法保存时,断言函数打印出this指向了对象本身,此时,this可以访问对象中的变量。
以上两种方式的调用可以帮助我们更好的理解函数的上下文环境。
当然还有一种调用:

3、作为constructor(构造函数)调用:

There’s nothing special about a function that’s going to be used as a constructor. Constructor functions are declared just like any other functions, and we can easily use function declarations and function expressions for constructing new objects.

构造函数和其他函数相比并没有什么不同之处,构造函数的声明也和其他函数一样,我们可以轻松利用函数声明和函数表达式去构建一个新的对象。

function Ninja() {
this.skulk = function() {
return this;
};
}
var ninja1 = new Ninja();
var ninja2 = new Ninja();
assert(ninja1.skulk() === ninja1,
"The 1st ninja is skulking");
assert(ninja2.skulk() === ninja2,
"The 2nd ninja is skulking");

当我们创造了一个函数名为Ninja,然后利用关键字new去调用时,一个新的空对象就被创建成功。
通常来说,当一个构造函数被调用,有以下几个特殊的行为被触发:

1、A new empty object is created.
2 、This object is passed to the constructor as the this parameter, and thus becomes the constructor’s function context.
3、 The newly constructed object is returned as the new operator’s value (with an exception that we’ll get to in short order).

1、一个新的空对象被创建
2、此对象做为this参数被传递给构造函数,由此变为构造函数的上下文对象
3、新构造的对象将作为new运算符的值返回

4、apply and call

function juggle() {
var result = 0;
for (var n = 0; n < arguments.length; n++) {
result += arguments[n];
}
this.result = result;
}
var ninja1 = {};
var ninja2 = {};
juggle.apply(ninja1,[1,2,3,4]);
juggle.call(ninja2, 5,6,7,8);
assert(ninja1.result === 10, "juggled via apply");
assert(ninja2.result === 26, "juggled via call");

持续更新中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁锅炖大鹅(e)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值