我们可以传递不可变的变量引用作为函数中的参数吗?
例:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
Answers:
由于JavaScript不支持通过引用传递参数,因此您需要将变量设置为对象:
var x = {Value: 0};
function a(obj)
{
obj.Value++;
}
a(x);
document.write(x.Value); //Here i want to have 1 instead of 0
在这种情况下,x是对对象的引用。当x传递给函数时a,该引用将复制到obj。因此,obj与x内存中的引用相同。改变的Value属性obj影响到的Value属性x。
Javascript将始终按值传递函数参数。那只是语言的规范。您可以x在两个函数的局部作用域中创建,而根本不传递变量。
这个问题可能会有所帮助: 如何在javascript中通过引用传递变量?从ActiveX函数读取数据,该函数返回多个值
总而言之,Javascript基本类型总是按值传递,而对象内部的值则按引用传递(感谢注释者指出我的疏忽)。因此,为了解决这个问题,您必须将整数放入对象内:
var myobj = {x:0};
function a(obj)
{
obj.x++;
}
a(myobj);
alert(myobj.x); // returns 1
x按值传递值时,无论是否x是对象,您都无法以调用者看到的任何方式将其替换为其他值。
我发现实现指针的方式略有不同,从C角度来看,它也许更通用并且更易于理解(因此更适合于用户示例的格式)。
在JavaScript中,就像在C语言中一样,数组变量实际上只是指向数组的指针,因此您可以使用与声明指针完全相同的数组。这样,即使您在原始对象中为变量命名,也可以以相同的方式使用代码中的所有指针。
它还允许使用两种不同的符号来表示指针的地址和指针的地址。
这是一个示例(我使用下划线表示指针):
var _x = [ 10 ];
function foo(_a){
_a[0] += 10;
}
foo(_x);
console.log(_x[0]);
产量
output: 20
答案很晚,但是我遇到了一种通过闭包通过引用传递原始值的方法。创建指针相当复杂,但是可以工作。
function ptr(get, set) {
return { get: get, set: set };
}
function helloWorld(namePtr) {
console.log(namePtr.get());
namePtr.set('jack');
console.log(namePtr.get())
}
var myName = 'joe';
var myNamePtr = ptr(
function () { return myName; },
function (value) { myName = value; }
);
helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack
在ES6中,可以缩短代码以使用lambda表达式:
var myName = 'joe';
var myNamePtr = ptr(=> myName, v => myName = v);
helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack
在JavaScript中,这将是全球性的。但是,您的函数看起来更像这样:
function a(){
x++;
};
由于x处于全局上下文中,因此您无需将其传递给函数。
Javascript应该只是将指针放入混合类,因为它解决了很多问题。这意味着代码可以引用未知的变量名称或动态创建的变量。它还使模块化编码和注入变得容易。
我认为这是实践中您可以最接近C指针的地方
在js中:
var a = 78; // creates a var with integer value of 78
var pointer = 'a' // note it is a string representation of the var name
eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12
在C:
int a = 78; // creates a var with integer value of 78
int pointer = &a; // makes pointer to refer to the same address mem as a
*pointer = 12; // changes the value of a to 12
由于JavaScript没有Perl的“ \”运算符来通过引用获取基元,所以这可能是不可能的,但是有一种方法可以使用此模式为基元创建“有效的指针”对象。
该解决方案最适合您已经拥有原语的情况(因此,您不再可以将其放入对象中而无需修改其他代码),但是仍然需要传递指向它的指针,以便代码的其他部分进行修改状态 因此您仍然可以使用行为类似于指针的无缝代理来修改其状态。
var proxyContainer = {};
// | attaches a pointer-lookalike getter/setter pair
// | to the container object.
var connect = function(container) {
// | primitive, can't create a reference to it anymore
var cant_touch_this = 1337;
// | we know where to bind our accessor/mutator
// | so we can bind the pair to effectively behave
// | like a pointer in most common use cases.
Object.defineProperty(container, 'cant_touch_this', {
'get': function() {
return cant_touch_this;
},
'set': function(val) {
cant_touch_this = val;
}
});
};
// | not quite direct, but still "touchable"
var f = function(x) {
x.cant_touch_this += 1;
};
connect(proxyContainer);
// | looks like we're just getting cant_touch_this
// | but we're actually calling the accessor.
console.log(proxyContainer.cant_touch_this);
// | looks like we're touching cant_touch_this
// | but we're actually calling the mutator.
proxyContainer.cant_touch_this = 90;
// | looks like we touched cant_touch_this
// | but we actually called a mutator which touched it for us.
console.log(proxyContainer.cant_touch_this);
f(proxyContainer);
// | we kinda did it! :)
console.log(proxyContainer.cant_touch_this);
在JavaScript中,您不能通过引用函数来传递变量。但是,您可以通过引用传递对象。
我在想与C或任何带指针的语言相反:
/** Javascript **/
var o = {x:10,y:20};
var o2 = {z:50,w:200};
。
o == o2 // obviously false : not the same address in memory
o <= o2 // true !
o >= o2 // also true !!
那是一个很大的问题:
这意味着您可以列出/管理应用程序创建(分配)的每个对象,
从庞大的对象列表中,计算有关这些对象的一些信息(例如,如何将它们链接在一起)
但是,当您想检索有关特定对象创建的信息时,就无法通过二分法在庞大的列表中找到它:每个对象都没有唯一的标识符,可以代替真实的内存地址
如果您要使用javascript编写,这最终意味着这是一个巨大的问题:
根据您要执行的操作,您可以简单地保存变量名,然后像下面这样访问它:
function toAccessMyVariable(variableName){
alert(window[variableName]);
}
var myFavoriteNumber = 6;
toAccessMyVariable("myFavoriteNumber");
要应用于您的特定示例,您可以执行以下操作:
var x = 0;
var pointerToX = "x";
function a(variableName)
{
window[variableName]++;
}
a(pointerToX);
alert(x); //Here I want to have 1 instead of 0
window对象。另外,不建议使用全局变量,因为可能已经有一个具有相同名称的变量。
它只是不支持指针,故事的结尾:-(。
我想补充一点,虽然我是新手并且来自C背景,但是从我所读到的有关事件循环和堆栈的内容来看,您应该使任何一个对象尽可能地靠近其调用者。因为我是新手,所以我可能会遇到这个错误。
这里有很多答案建议将其设置为全局,但是如果我没有正确阅读的话,那么这又可能会增加堆栈跳数,并在某种程度上可能不必要地分割事件循环(取决于被调用对象当前正在执行的操作)。
同样,任何给出的模仿指针的示例在很多方面都只能做一个相同的事情,而不会成为指针。
你不能。浏览器不允许您访问系统内存及其变量。像环境这样的节点应该可以实现,但是除非您是黑客,否则在浏览器内部不太可能实现。