Проходит ли Javascript по ссылке?

Передает ли Javascript по ссылкам или передает значения? Вот пример из Javascript: The Good Parts. Я очень смущен параметром my для функции прямоугольника. Это фактически undefined и переопределено внутри функции. Нет оригинальной ссылки. Если я удалю его из параметра функции, функция внутренней области не сможет получить к ней доступ.

Это закрытие? Но функция не возвращается.

var shape = function (config) {
    var that = {};
    that.name = config.name || "";
    that.area = function () {
        return 0;
    };
    return that;
};
var rectangle = function (config, my) {
    my = my || {};
    my.l = config.length || 1;
    my.w = config.width || 1;
    var that = shape(config);
    that.area = function () {
        return my.l * my.w;
    };
    return that;
};
myShape = shape({
    name: "Unhnown"
});
myRec = rectangle({
    name: "Rectangle",
    length: 4,
    width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());
+299
27 окт. '12 в 21:50
источник поделиться
12 ответов

Примитивы передаются по значению, Объекты передаются по "копии ссылки".

В частности, когда вы передаете объект (или массив), вы (невидимо) передаете ссылку на этот объект, и возможно изменить содержимое этого объекта, но если вы попытаетесь перезаписать ссылку, это не повлияет на копию ссылка, удерживаемая вызывающей стороной, т.е. сама ссылка передается по значению:

function replace(ref) {
    ref = {};           // this code does _not_ affect the object passed
}

function update(ref) {
    ref.key = 'newvalue';  // this code _does_ affect the _contents_ of the object
}

var a = { key: 'value' };
replace(a);  // a still has its original value - it unmodfied
update(a);   // the _contents_ of 'a' are changed
+549
27 окт. '12 в 21:51
источник

Подумайте об этом так:

Всякий раз, когда вы создаете объект в ECMAscript, этот объект формируется в универсальном универсальном месте ECMAscript, где никто никогда не сможет получить. Все, что вы вернетесь, это ссылка на этот объект в этом мистическом месте.

var obj = { };

Четный obj - это только ссылка на объект (который находится в этом замечательном месте), и, следовательно, вы можете передать эту ссылку только. Фактически, любой фрагмент кода, который обращается к obj, будет изменять объект, который находится далеко, далеко.

+52
27 окт. '12 в 21:55
источник
другие ответы

Связанные вопросы


Похожие вопросы

Мои 2 цента... Не имеет значения, передает ли Javascript параметры по ссылке или значению. Что действительно важно, так это назначение vs mutation.

Я написал более длинное, более подробное объяснение здесь (Является ли JavaScript паролем или языком по-умолчанию?)

Когда вы передаете что-либо (будь то объект или примитив), все javascript это назначает новую переменную, находясь внутри функции... точно так же, как использовать знак равенства (=)

Как этот параметр ведет себя внутри функции точно такой же, какой он будет вести, если вы просто назначили новую переменную с помощью знака равенства. Возьмите эти простые примеры.

var myString = 'Test string 1';

// Assignment - A link to the same place as myString
var sameString = myString;

// If I change sameString, it will not modify myString, 
// it just re-assigns it to a whole new string
sameString = 'New string';

console.log(myString); // logs 'Test string 1';
console.log(sameString); // logs 'New string';

Если мне нужно передать myString в качестве параметра функции, она ведет себя так, как будто я просто назначил ее новой переменной. Теперь сделаем то же самое, но с функцией вместо простого назначения

function myFunc(sameString) {

    // Re assignment.. again, it will not modify myString
    sameString = 'New string';
}

var myString = 'Test string 1';

// This behaves the same as if we said sameString = myString
myFunc(myString);

console.log(myString); // Again, logs 'Test string 1';

Единственная причина, по которой вы можете изменять объекты при передаче их функции, - это то, что вы не переназначаете... Вместо этого объекты могут быть изменены или изменены. Опять же, это работает так же.

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'

Если мне нужно передать myObject в качестве параметра функции, он ведет себя так, как будто я просто назначил его новой переменной. Опять же, то же самое с точно таким же поведением, но с функцией.

function myFunc(sameObject) {

    // We mutate the object, so the myObject gets the change too... just like before.
    sameObject.name = 'Jill';

    // But, if we re-assign it, the link is lost
    sameObject = { name: 'Howard' };
}

var myObject = { name: 'Joe'; }

// This behaves the same as if we said sameObject = myObject;
myFunc(myObject);
console.log(myObject.name); // Logs 'Jill'

Каждый раз, когда вы передаете переменную функции, вы "назначаете" любое имя этого параметра, как если бы вы использовали знак равенства (=).

Всегда помните, что знак равенства (=) означает назначение. Передача параметра функции также означает назначение. Они одинаковы, и 2 переменные связаны точно так же.

Единственный момент, когда изменение переменной влияет на другую переменную, - это когда базовый объект мутирован.

Нет смысла делать различия между объектами и примитивами, потому что он работает точно так же, как если бы у вас не было функции, и просто использовал знак равенства для назначения новой переменной.

+34
07 авг. '14 в 7:49
источник

Как и в случае C, все передается по значению. В отличие от C, вы не можете создать резервную копию и передать местоположение переменной, потому что у нее нет указателей только для ссылок.

И ссылается, что это все объекты, а не переменные. Существует несколько способов достижения одного и того же результата, но их нужно делать вручную, а не просто добавлять ключевое слово на сайт вызова или объявления.

+14
28 окт. '12 в 1:43
источник

Аргументы функции передаются либо по значению, либо по разделению, но никогда НИКОГДА по ссылке в Javascript!

Вызов по значению

Примитивные типы передаются по значению:

var num = 123, str = "foo";

function f(num, str) {
  num += 1;
  str += "bar";
  console.log("inside of f:", num, str);
}

f(num, str);
console.log("outside of f:", num, str);

Переназначения внутри области действия не видны в окружающей области.

Это также относится к String s, которые являются составным типом данных и все же неизменяемы:

var str = "foo";

function f(str) {
  str[0] = "b"; // doesn't work, because strings are immutable
  console.log("inside of f:", str);
}

f(str);
console.log("outside of f:", str);

Call-по-Sharing

Объекты, то есть все типы, которые не являются примитивами, передаются путем совместного использования. Переменная, которая содержит ссылку на объект, на самом деле содержит просто копию этой ссылки. Если Javascript будет использовать стратегию оценки Call-by-reference, переменная будет содержать исходную ссылку. Это принципиальное различие между передачей и ссылкой.

Каковы практические последствия этого различия?

var o = {x: "foo"}, p = {y: 123};

function f(o, p) {
  o.x = "bar"; // mutation
  p = {x: 456}; // reassignment
  console.log("o inside of f:", o);
  console.log("p inside of f:", p);
}

f(o, p);

console.log("o outside of f:", o);
console.log("p outside of f:", p);

Мутирование означает изменение определенных свойств существующего Object. Эталонная копия, с которой связана переменная и которая ссылается на этот объект, остается неизменной. Таким образом, мутации видны в области вызова.

Переназначение означает замену эталонной копии, связанной с переменной. Поскольку это всего лишь копия, другие переменные, содержащие копию той же ссылки, остаются неизменными. Таким образом, переназначения не отображаются в области действия вызывающего абонента, как это было бы в стратегии оценки по вызову.

Дополнительная информация о стратегии оценки в Ecmascript.

+11
22 июл. '16 в 19:05
источник

JavaScript передается по значению. Для примитивов передается примитивное значение. Для объектов передается ссылка "значение" объекта.

Пример с объектом:

var f1 = function(inputObject){
    inputObject.a=2;
}
var f2 = function(){
    var inputObject={"a":1};
    f1(inputObject); 
    console.log(inputObject.a);
}

вызов f2 приводит к выделению значения "a" как 2 вместо 1, когда эта ссылка передается и обновляется значение "a" в ссылке.

Пример с примитивным:

var f1 = function(a){
    a=2;
}
var f2 = function(){
    var a =1;
    f1(a); 
    console.log(a);
}

вызов f2 приводит к печати значения "a" как 1.

+6
08 мар. '14 в 8:48
источник

В практическом плане Alnitak является правильным и позволяет легко понять, но, в конечном счете, в JavaScript все передается по значению.

Что такое "значение" объекта? Это ссылка на объект.

Когда вы передаете объект, вы получаете копию этого значения (отсюда и "копия ссылки", описанная Алнитаком). Если вы измените это значение, вы не измените исходный объект, вы измените свою копию этой ссылки.

+4
22 нояб. '13 в 19:39
источник

В интересах создания простого примера, который использует const...

const myRef = { foo: 'bar' };
const myVal = true;

function passes(r, v) {
  r.foo = 'baz';
  v = false;
}

passes(myRef, myVal);

console.log(myRef, myVal); // Object {foo: "baz"} true
+4
22 авг. '17 в 19:12
источник

"Глобальные" переменные javascript являются членами объекта window. Вы можете получить доступ к ссылке в качестве члена объекта окна.

var v = "initialized";
function byref(ref) {
 window[ref] = "changed by ref";
}
byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// could also be called like... byref('v');
console.log(v); // outputs changed by ref

Обратите внимание, что приведенный выше пример не будет работать для переменных, объявленных внутри функции.

+3
24 июл. '14 в 21:49
источник

Без пуризмов, я думаю, что лучший способ эмулировать скалярный аргумент по ссылке в Javascript - это использовать объект, как говорит предыдущий ответ.

Тем не менее, я делаю немного по-другому:

Я сделал присвоение объекта внутри вызова функции, чтобы можно было видеть ссылочные параметры рядом с вызовом функции. Это увеличивает читабельность источника

В объявлении функции я поместил свойства как комментарий, по той же причине: удобочитаемость.

var r;

funcWithRefScalars(r = {amount:200, message:null} );
console.log(r.amount + " - " + r.message);


function funcWithRefScalars(o) {  // o(amount, message)
  o.amount  *= 1.2;
  o.message = "20% increase";
}

В приведенном выше примере null четко указывает выходной опорный параметр.

Выход:

240 - 20% Increase

На стороне клиента console.log должен быть заменен на alert.

★ ★ ★

Еще один метод, который может быть еще более читабельным:

var amount, message;

funcWithRefScalars(amount = [200], message = [null] );
console.log(amount[0] + " - " + message[0]);

function funcWithRefScalars(amount, message) {  // o(amount, message)
   amount[0]  *= 1.2;
   message[0] = "20% increase";
}

Здесь вам не нужно даже создавать новые фиктивные имена, как r выше.

+1
09 мар. '18 в 17:46
источник

Примитивы передаются по значению. Но в случае, если вам нужно только прочитать значение примитива (а значение не известно во время вызова функции), вы можете передать функцию, которая извлекает значение в тот момент, когда вам это нужно.

function test(value) {
  console.log('retrieve value');
  console.log(value());
}

// call the function like this
var value = 1;
test(() => value);
0
24 янв. '19 в 12:08
источник

Я не вижу ссылки на примеры, когда люди пытаются это продемонстрировать. Я вижу только передачу по значению.

В случае переменных, которые содержат ссылку на объект, ссылка является значением этих переменных, и, следовательно, ссылка передается, которая затем передается по значению.

в таком заявлении:

var a = {
  b:"foo", 
  c:"bar"
};

Значение 'a' - это не Объект, а (пока что) ссылка на него. Другими словами, объект не находится в переменной a, ссылка на него есть. Я думаю, что это то, что кажется трудным для программистов, которые в основном знакомы только с JavaScript. Но легко для людей, которые знают также, например, Java, С# и C.

0
29 янв. '19 в 20:07
источник

Посмотрите другие вопросы по меткам или Задайте вопрос