Чи можемо ми передати посилання на змінну, яка є незмінною як аргумент у функції?
Приклад:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
Чи можемо ми передати посилання на змінну, яка є незмінною як аргумент у функції?
Приклад:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
Відповіді:
Оскільки 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є це об’єкт чи ні, ви не можете замінити його цілим іншим значенням будь-яким способом, який побачить абонент.
Я знайшов дещо інший спосіб реалізації покажчиків, який є, можливо, більш загальним і простішим для розуміння з точки зору С (і, отже, більше вписується у формат прикладу користувачів).
В 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 код можна скоротити, використовуючи лямбда-вирази:
var myName = 'joe';
var myNamePtr = ptr(=> myName, v => myName = v);
helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack
У JavaScript це було б глобальним. Однак ваша функція буде виглядати приблизно так:
function a(){
x++;
};
Оскільки xце в глобальному контексті, вам не потрібно передавати його у функцію.
Javascript повинен просто розміщувати покажчики в суміші, оскільки це вирішує багато проблем. Це означає, що код може посилатися на невідоме ім'я змінної або змінні, які були створені динамічно. Це також полегшує модульне кодування та введення.
Це те, що я бачу як найближче до практичних вказівок
в 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:
JavaScript не підтримує передачу примітивних типів за посиланням. Однак є обхідне рішення.
Помістіть усі змінні, які потрібно передати в об'єкт. В цьому випадку є тільки одна змінна, x. Замість передачі змінної передайте ім'я змінної як рядок, що є "x".
var variables = {x:0};
function a(x)
{
variables[x]++;
}
a("x");
alert(variables.x);
Залежно від того, що ви хочете зробити, ви можете просто зберегти ім'я змінної, а потім отримати доступ до нього пізніше приблизно так:
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, з того, що я читаю про цикл подій та стек, ви повинні тримати будь-який об'єкт якомога ближче до свого абонента. Оскільки я абсолютно новий, я міг це помилити.
Багато відповідей тут пропонують зробити його глобальним, але знову ж таки, якщо я читаю правильно, це, можливо, може збільшити стрибки стека і певним чином, можливо, непотрібно фрагментувати ваш цикл подій (залежно від того, що викликаний об'єкт зараз робить).
Крім того, будь-який приклад, що імітує вказівники, - це лише 1 багатьма способами робити одне і те ж, що не буде вказівником.
У вашому прикладі ви насправді маєте 2 змінні з однаковим іменем. (Глобальна) змінна x і змінна сфери функції x. Цікаво побачити, що при виборі того, що робити з 2 однойменними змінними, javascript поєднується з назвою функції і ігнорує змінну, що не входить в область дії.
Можливо, не безпечно припускати, що javascript завжди буде поводитися так ...
Ура!
Ні, ви не можете. Браузер не надає вам доступу до системної пам'яті та її змінних. Це повинно бути можливо з таким середовищем, як вузол, але всередині браузера це не зовсім можливо, якщо ви не хакер.