javascript 引用传递

在 Javascript 中,我们使用函数并且传递参数来调用函数。但是 Javascript 到底是如果传递你所传递的参数呢?当你开始面向对象的开发时,你可能会陷入有时可以访问你的对象有时又不能访问困惑。

在传递字符串或数字的这样的基本类型变量时,情况是按值传递的。这意味着,在函数中对该变量所做的任何更改都不会影响到外部的传递竟来的变量。让我们来看看下面的例子:


function myfunction(x) {
	// x 等于 4
	x = 5;
	// x 现在是 5
}

var x = 4;
console.log(x); // x 等于 4
myfunction(x);
console.log(x); // x 依然是 4

然而,在传递对象的时候是通过引用传递的。在这种情况下,该对象任何属性在函数中都是可以被改变的,让我们来看看另一个例子:


function myClass() {
	this.value = 5;
}

var obj = new myClass();
console.log(obj.value); // obj.value = 5

function fun(f) {
	f.value = 6;
}

fun(obj); // 函数中改变对象的值
console.log(obj.value); // obj.value 现在等于 6

所以,当你传递对象的时候会发生什么?大多数人会觉得(或者至少我觉得),它会通过引用传递可以访问它属性的方法。不幸的是,事实并非如此。看看这个例子:


function myClass() {
	this.value = 5;
}

myClass.prototype.add = function() {
	this.value++;
}

var o = new myClass();
console.log(o.value); // o.value = 5

o.add();
console.log(o.value); // o.value = 6

function fun(f) {
	f(); // 运行传递进来的函数
}

fun(o.add); // 调用对象的函数
console.log(o.value); // sorry, 依旧是 6

这里的问题是使用“this” 关键字。这是一个指向当前对象的上下文便捷引用。虽然我们将函数作为参数传递了进去,但是我们并没有把当前对象(当前的“this”)也一同传递进去,所以执行改函数的时候对象上下文丢失。更准确地说,this现在指向新函数调用的上下文而不是我们刚刚传递进来的对象的函数的上下文。对于一个独立的函数二样, this 可能是 window 对象的上下文,对于时间调用的函数二样, this 可能是一个 event object。简单的证明示例:

// node.js 默认全局变量是 global
if (typeof window !== 'undefined') {
	// 客户端 js 默认是 window
	global = window;
}

function fun() {
	console.log('this === global: ' + (this === global)); // true
}

fun();

function myClass() {

}

myClass.prototype.test = function() {
	console.log('this === global: ' + (this === global));
	console.log('this instanceof myClass: ' + (this instanceof myClass));
};

var c = new myClass();
c.test();

结果

this === global: true
this === global: false
this instanceof myClass: true

解决方案:

1.当你知道方法名的时候


function objectchanger(obj) {
	obj.add(); // 将对象传递进来,通过对象调用函数
}
objectchanger(o);
alert(o.value); // 值为 7

2.当你不知道方法名的时候


function objectchanger(fnc, obj) {
	fnc.call(obj); // 通过 call 来调用函数,并指定其 this 指向。
}
objectchanger(o.add, o);
alert(o.value); // 值为 7

英文原文:http://snook.ca/archives/javascript/javascript_pass

很久以前看的文章存在草稿箱今天顺便拿出来翻译了。其实有挺多想总结的但是一下子憋不出来,就不多引申了。

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s