Назначение функции-указателя Javascript

Рассмотрим этот код javascript:

var bar = function () { alert("A"); }
var foo = bar;
bar = function () { alert("B"); };
foo();

При запуске этого кода я получаю "A". Является ли это поведение частью спецификации javascript и могу ли я на него положиться?

Ответ 1

Да, что ожидается и по дизайну.

Ваш вопрос в основном: foo ссылка bar как указатель или ссылка на другом языке?

Ответ: нет: значение bar во время присвоения присваивается foo.

Ответ 2

В других примерах ничего не было принято по значению; все было передано по ссылке.

bar и foo - BOTH указатели

Все vars/handle для NON примитивных объектов в javascript являются указателями; указатели ARE являются родными для javascript, они по умолчанию.

var bar = function () { alert("A"); } //bar is a pointer to function1
var foo = bar;  //pointer copied; foo is now also a pointer to function1
bar = function () { alert("B"); };  //bar points to function2
foo();  //foo is still a pointer to function1

Вы столкнетесь с скрытыми ошибками и ошибками, если считаете, что это копии. Тем более, если вы работаете со сложными объектами. Например

function person(name){this.name = name}
var john = new person("john")
var backup = john
backup.name //john
john.name = "jack"
backup.name //jack, NOT john

На самом деле COPY не-примитив в javascript требует больше работы, чем просто a = b. Например:

function person(name){  this.name = name}
var john = new person("john")
var backup = new Object()
backup = JSON.parse(JSON.stringify(john))
backup.__proto__ = john.__proto__   //useful in some cases
john.name = "jack"
backup.name //john

Ответ 3

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

Лучше не думать в терминах указателей и ссылок на память при обсуждении внутренних компонентов JavaScript (или ECMAScript) при работе со спецификациями. Переменные - это записи среды внутри и хранятся и ссылаются по имени, а не по адресу памяти. Что делает ваш оператор присваивания, как внутри, так и по дизайну, ищет имя записи среды ( "foo" или "bar" ) и присваивает значение этой записи.

Итак,

var bar = function () { alert("A"); }

назначает значение "bar" для записи среды (анонимная функция).

var foo = bar;

внутренне вызывает GetValue ( "bar" ), который извлекает значение, связанное с записью "bar", а затем связывает это значение с записью "foo". Следовательно, впоследствии исходное значение бара все еще можно использовать, поскольку оно теперь связано с foo.

Поскольку ссылки на JavaScript по строкам, а не по адресу памяти, именно поэтому вы можете делать такие вещи:

someObject["someProperty"]

который ищет значение, основанное на имени свойства.

Ответ 4

Да, нет ничего особенного в том, что переменные относятся к функциям, там нет сглаживания.

var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1

Ответ 5

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

Вот несколько примеров:

"obj2" является ссылкой "obj1" , вы меняете "obj2", а "obj1" изменяется. Он будет предупреждать false.

var obj1 = {prop:true},
    obj2 = obj1;
obj2.prop = false;
alert(obj1.prop);

"prop" указывает на свойство, которое не является объектом, "prop" не является указателем на этот объект, а является копией. Если вы измените "prop" , "obj1" не будет изменен. Он будет предупреждать true

var obj1 = {prop:true},
    prop = obj1.prop;
prop = false;
alert(obj1.prop);

"obj2" является ссылкой на свойство "subObj" "obj1" . если "obj2" изменено, "obj1" изменяется. Он будет предупреждать false.

var obj1 = {subObj:{prop:true}},
    obj2 = obj1.subObj;
obj2.prop = false;
alert(obj1.subObj.prop);

Ответ 6

Да, это правильное поведение.

//create variable bar and assign a function to it
var bar = function () { alert("A"); }
//assign value of bar to the newly created variable foo
var foo = bar;
//assign a new function to the variable bar
//since foo and bar are not pointers, value of foo doesn't change
bar = function () { alert("B"); };
//call the function stored in foo
foo();

Ответ 7

Это не указатели на функции (и в JS нет указателей). Функции в JS могут быть анонимными и являются объектами первого класса. Следовательно

function () { alert("A"); }

создает анонимную функцию, которая предупреждает "A" о выполнении;

var bar = function () { alert("A"); };

назначьте эту функцию bar;

var foo = bar;

назначить foo в bar, что является функцией "A".

bar = function () { alert("B"); };

для функции анонимной функции "B". Это не повлияет на foo или другую функцию "A".

foo();

Вызвать функцию, сохраненную в foo, которая является функцией "A".


Собственно на языках, где есть функциональные точки, например. C он не повлияет на foo. Я не знаю, где вы получаете идею получения "B" при переназначении.

void A(void) { printf("A\n"); }
void B(void) { printf("B\n"); }
typedef void(*fptr_t)(void);
fptr_t foo = A;
fptr_t bar = foo;
bar = B;
foo(); // should print "A"

Ответ 8

Это назначение переменной неназванной функции, а не указатель на функцию

Ответ 9

Да, вы создали указатель на оригинальную функцию "A". Когда вы переназначаете панель, вы переназначаете ее, но вы все равно оставляете ссылки на старую функцию в одиночку.

Итак, чтобы ответить на ваш вопрос, да, вы можете положиться на него.

Ответ 10

Я хотел бы добавить это, также работает и для заранее определенных именованных функций:

function myfunc() { alert("A"); }
var bar = myfunc;
var foo = bar;
bar = function () { alert("B"); };
foo();

Это сделает то же самое, указывая, что имена функций действуют как имена массивов (указатели).

Ответ 11

Для каждого FunctionDeclaration f в коде в исходном текстовом порядке выполните:

Пусть fn - Идентификатор в FunctionDeclaration f.

Пусть fo является результатом экземпляра FunctionDeclaration f, как описано в разделе 13.

Пусть funcAlreadyDeclared является результатом вызова envs HasBinding конкретного метода, передающего fn в качестве аргумента.

Если funcAlreadyDeclared является ложным, вызовите envs CreateMutableBinding конкретный метод, передающий fn и configurableBindings в качестве аргументов.

Ссылки