Проходит ли 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());

Ответы

Ответ 1

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

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

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

Ответ 2

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

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

var obj = { };

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

Ответ 3

Мои 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 переменные связаны точно так же.

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

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

Ответ 4

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

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

Ответ 5

Аргументы функции передаются либо по значению, либо по разделению, но никогда НИКОГДА по ссылке в 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);

Ответ 6

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.

Ответ 7

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

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

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

Ответ 8

В интересах создания простого примера, который использует 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

Ответ 9

"Глобальные" переменные 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

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

Ответ 10

Без пуризмов, я думаю, что лучший способ эмулировать скалярный аргумент по ссылке в 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 выше.

Ответ 11

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

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

// call the function like this
var value = 1;
test(() => value);

Ответ 12

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

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

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

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

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