Вы должны взглянуть на Remoting
Разница заключается в том, что Например, выражение функции: functionOne
является выражением функции и поэтому определяется только при достижении этой строки, тогда как functionTwo
является объявлением функции и определяется, как только выполняется его окружающая функция или скрипт (из-за грузоподъемный [/ д0]). // TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
И объявление функции:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
Это также означает, что вы не можете условно определять функции с помощью объявлений функций:
if (test) {
// Error or misbehavior
function functionThree() { doSomething(); }
}
Вышеупомянутое фактически определяет functionThree
независимо значения test
; если use strict
не действует, и в этом случае он просто вызывает ошибку.
Они довольно похожи с некоторыми небольшими отличиями, во-первых, это переменная, которая назначается анонимной функции (Объявление функции), а вторая - обычным способом создания функции в JavaScript (анонимная декларация функции), у обоих есть использование, минусы и плюсы:
1. Функция Expression
var functionOne = function() {
// Some code
};
Функция Expression определяет функцию как часть синтаксиса большего выражения (обычно назначение переменной). Функции, определенные с помощью функций Выражения, можно назвать или анонимными. Выражения функции не должны начинаться с «функции» (следовательно, круглые скобки вокруг примера самозапуска).
Назначить переменную функции, значит нет Подъем, так как мы знаем, что функции в JavaScript могут Hoist, означает, что их можно вызвать до того, как они будут объявлены, а переменные должны быть объявлены до получения доступа к ним, поэтому в этом случае мы не можем получить доступ к функции до того, где она объявлена, также это может быть способ, которым вы пишете свои функции для функций, возвращающих другую функцию, такая декларация может иметь смысл, также в ECMA6 & amp; выше вы можете назначить это функции стрелки, которая может использоваться для вызова анонимных функций, также этот способ объявления - лучший способ создания функций конструктора в JavaScript.
2. Объявление функции
function functionTwo() { // Some code }
Объявление функции определяет именованную функциональную переменную без необходимости назначения переменной. Объявление функций происходит как автономные конструкции и не может быть вложено внутри не-функциональных блоков. Полезно подумать о них как о братьях и сестрах переменных объявлений. Так же, как объявления переменных должны начинаться с «var», декларации функций должны начинаться с «функции».
Это обычный способ вызова функции в JavaScript, эта функция может быть вызвана перед вами даже объявите его, как и в JavaScript, все функции получают Hoisted, но если вы используете «strict», это не будет Hoist, как ожидалось, это хороший способ вызвать все обычные функции, которые не являются большими в строках и не являются конструкторской функцией.
Кроме того, если вам нужна дополнительная информация о том, как работает подъем в JavaScript, перейдите по ссылке ниже:
https://developer.mozilla.org/en-US/docs / Глоссарий / Подъемно
var myFunc = null;
вне цикла или вне блока if / elseif / else. Затем вы можете условно назначить разные функции одной и той же переменной. В JS лучше назначить отсутствующее значение null, а затем не определено. Поэтому сначала следует объявить myFunction как null, а затем назначить его позже, условно.
– Alexander Mills
26 May 2015 в 20:31
...also this way of declaring is a better way to create Constructor functions in JavaScript
, пожалуйста, уточните, мне любопытно!
– Karl Morrison
13 June 2017 в 12:44
@EugeneLazutkin дает пример, где он называет назначенную функцию, чтобы иметь возможность использовать shortcut()
как внутреннюю ссылку на себя. Джон Ресиг дает другой пример - копирование рекурсивной функции, назначенной другому объекту в его учебном пособии Learning Advanced Javascript . Хотя назначение функций свойствам не является строго вопросом здесь, я рекомендую активно пробовать учебник - запустите код, нажав кнопку в правом верхнем углу, и дважды щелкните код для редактирования по своему вкусу.
Примеры из учебника: рекурсивные вызовы в yell()
:
Тесты завершаются, когда исходный объект ниндзя удален. (стр. 13)
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
var samurai = { yell: ninja.yell };
var ninja = null;
try {
samurai.yell(4);
} catch(e){
assert( false, "Uh, this isn't good! Where'd ninja.yell go?" );
}
Если вы назовете функцию, которая будет называться рекурсивно, тесты пройдут. (стр. 14)
var ninja = {
yell: function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" );
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
Объявление функции и выражение функции, присваиваемое переменной, ведут себя одинаково после установления привязки.
Однако существует , как и , когда объект функции фактически связан с его переменной. Это различие связано с механизмом, называемым изменением подъема в JavaScript.
В принципе, все объявления функций и объявления переменных поднимаются в начало функции в котором происходит объявление (поэтому мы говорим, что JavaScript имеет область функций ).
undefined
в начале тела функции и будет присвоена значение в исходном месте в коде. (На самом деле ему будет присвоено значение в в каждом месте, где появляется объявление переменной с тем же именем.) Порядок подъема также важен : объявления функций имеют приоритет над объявлениями переменных с тем же именем, а последнее объявление функции имеет приоритет над предыдущими объявлениями с таким же именем.
Некоторые примеры ...
var foo = 1;
function bar() {
if (!foo) {
var foo = 10 }
return foo; }
bar() // 10
Переменная foo
поднимается в начало функции, инициализируется на undefined
, так что !foo
является true
, поэтому foo
назначается 10
. foo
вне области bar
не играет никакой роли и нетронутой.
function f() {
return a;
function a() {return 1};
var a = 4;
function a() {return 2}}
f()() // 2
function f() {
return a;
var a = 4;
function a() {return 1};
function a() {return 2}}
f()() // 2
Объявление функций имеет приоритет над объявлениями переменных, а последнее объявление функции «прилипает».
function f() {
var a = 4;
function a() {return 1};
function a() {return 2};
return a; }
f() // 4
В этом примере инициализируется a
с результатом функции от оценки объявления второй функции, а затем назначается 4
.
var a = 1;
function b() {
a = 10;
return;
function a() {}}
b();
a // 1
Здесь объявление функции сначала открывается, объявляя и инициализируя переменную a
. Затем этой переменной присваивается 10
. Другими словами: присваивание не присваивается внешней переменной a
.
Другое отличие, которое не упоминается в других ответах, заключается в том, что если вы используете анонимную функцию
var functionOne = function() {
// Some code
};
и используете это как конструктор, как в
var one = new functionOne();
, тогда one.constructor.name
не будет определено. Function.name
является нестандартным, но поддерживается Firefox, Chrome, другими браузерами, основанными на Webkit, и IE 9 +.
С помощью
function functionTwo() {
// Some code
}
two = new functionTwo();
можно получить имя конструктора как строки с two.constructor.name
.
Существует три примечательных сравнения между двумя различными декларациями функций, перечисленными ниже.
Выполняется следующее, поскольку function add()
имеет область действия до ближайшего блока:
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
function add(a, b){
return a + b;
}
Следующее не работает (потому что var add=
superseeds function add()
).
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function add(a, b){
return a + b;
}
Не работает, поскольку add
объявлен после использования.
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function(a, b){
return a + b;
}
Имя функции function thefuncname(){}
является thefuncname , когда оно объявлено таким образом.
function foobar(a, b){}
console.log(foobar.name);
var a = function foobar(){};
console.log(a.name);
В противном случае, если функция объявлена как function(){}
, функция .name является первой переменной, используемой для хранения функции.
var a = function(){};
var b = (function(){ return function(){} });
console.log(a.name);
console.log(b.name);
Если нет переменные, установленные для функции, то имя функции - это пустая строка (""
).
console.log((function(){}).name === "");
Наконец, функция назначается для первоначального набора имени, successi переменные, заданные для функции, не меняют имя.
var a = function(){};
var b = a;
var c = b;
console.log(a.name);
console.log(b.name);
console.log(c.name);
В Google V8 и Firefox Spidermonkey может быть несколько разметок компиляции Microsecond JIST, но в итоге результат будет таким же. Чтобы убедиться в этом, давайте рассмотрим эффективность JSPerf в microbenchmarks, сравнив скорость двух фрагментов кода. Тесты JSPerf найдены здесь . И jsben.ch тесты найдены здесь . Как вы можете видеть, есть заметная разница, когда их не должно быть. Если вы действительно такой урод, как я, то это может быть более полезно, если вы попытаетесь уменьшить количество переменных и функций в области действия и, в частности, устранить полиморфизм (например, использовать одну и ту же переменную для хранения двух разных типов).
«Ближайший блок» - ближайшая «функция» (включая асинхронные функции, функции генератора и функции асинхронного генератора). Однако интересно, что function functionName() {}
ведет себя как var functionName = function() {}
, когда в блоке не замыкания элементы вне указанного закрытия.
var add=function(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}');
}
} catch(e) {
console.log("Is a block");
}
var add=function(a, b){return a + b}
function add(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
function add(a, b){
return a + b;
}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(function () {
function add(a, b){
return a + b;
}
})();
if
, else
, for
, while
, try
/ catch
/ finally
, switch
, do
/ while
, with
)
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
{
function add(a, b){
return a + b;
}
}
var add=function()
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
var add=function(a, b){
return a + b;
}
})();
function add()
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
function add(a, b){
return a + b;
}
})();
В свете аргумента «названные функции отображаются в стеках» аргументы, современные механизмы JavaScript на самом деле вполне способны представлять анонимные функции.
На момент написания этой статьи V8, SpiderMonkey, Chakra и Nitro всегда обратитесь к названным функциям по их именам. Они почти всегда ссылаются на анонимную функцию по ее идентификатору, если она есть.
SpiderMonkey может определить имя анонимной функции, возвращенной из другой функции. Остальное не может.
Если вы действительно хотите, чтобы ваш итератор и успешные обратные вызовы отображались в трассировке, вы могли бы назвать их тоже ...
[].forEach(function iterator() {});
Но
'use strict';
var a = function () {
throw new Error();
},
b = function b() {
throw new Error();
},
c = function d() {
throw new Error();
},
e = {
f: a,
g: b,
h: c,
i: function () {
throw new Error();
},
j: function j() {
throw new Error();
},
k: function l() {
throw new Error();
}
},
m = (function () {
return function () {
throw new Error();
};
}()),
n = (function () {
return function n() {
throw new Error();
};
}()),
o = (function () {
return function p() {
throw new Error();
};
}());
console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) {
return values.concat(e[key]);
}, [])).concat([m, n, o]).reduce(function (logs, func) {
try {
func();
} catch (error) {
return logs.concat('func.name: ' + func.name + '\n' +
'Trace:\n' +
error.stack);
// Need to manually log the error object in Nitro.
}
}, []).join('\n\n'));
func.name:
Trace:
Error
at a (http://localhost:8000/test.js:4:11)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: b
Trace:
Error
at b (http://localhost:8000/test.js:7:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: d
Trace:
Error
at d (http://localhost:8000/test.js:10:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at a (http://localhost:8000/test.js:4:11)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: b
Trace:
Error
at b (http://localhost:8000/test.js:7:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: d
Trace:
Error
at d (http://localhost:8000/test.js:10:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at e.i (http://localhost:8000/test.js:17:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: j
Trace:
Error
at j (http://localhost:8000/test.js:20:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: l
Trace:
Error
at l (http://localhost:8000/test.js:23:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at http://localhost:8000/test.js:28:19
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: n
Trace:
Error
at n (http://localhost:8000/test.js:33:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: p
Trace:
Error
at p (http://localhost:8000/test.js:38:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27 test.js:42
func.name:
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
e.i@http://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: j
Trace:
j@http://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: l
Trace:
l@http://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: n
Trace:
n@http://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: p
Trace:
p@http://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: undefined
Trace:
Error
at a (http://localhost:8000/test.js:4:5)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at b (http://localhost:8000/test.js:7:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at d (http://localhost:8000/test.js:10:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at a (http://localhost:8000/test.js:4:5)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at b (http://localhost:8000/test.js:7:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at d (http://localhost:8000/test.js:10:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at e.i (http://localhost:8000/test.js:17:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at j (http://localhost:8000/test.js:20:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at l (http://localhost:8000/test.js:23:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at Anonymous function (http://localhost:8000/test.js:28:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at n (http://localhost:8000/test.js:33:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at p (http://localhost:8000/test.js:38:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name:
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
i@http://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: j
Trace:
j@http://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: l
Trace:
l@http://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: n
Trace:
n@http://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: p
Trace:
p@http://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
Я добавляю свой собственный ответ только потому, что все остальные полностью закрыли платформу.
Я задавался вопросом, какой путь лучше уже давно, и благодаря http : //jsperf.com теперь я знаю:)
[/g1]
Объявление функций происходит быстрее, и это то, что действительно имеет значение в web dev right ? ;)
Сначала я хочу исправить Грега: function abc(){}
тоже облагается & mdash; имя abc
определяется в области, где это определение встречается. Пример:
function xyz(){
function abc(){};
// abc is defined here...
}
// ...but not here
Во-вторых, можно комбинировать оба стиля:
var xyz = function abc(){};
xyz
будет определяться как обычно, abc
не определено во всех браузеров, но Internet & nbsp; Explorer & mdash; не полагайтесь на его определение. Но он будет определен внутри своего тела:
var xyz = function abc(){
// xyz is visible here
// abc is visible here
}
// xyz is visible here
// abc is undefined here
Если вы хотите выполнять функции псевдонима во всех браузерах, используйте этот вид объявления:
function abc(){};
var xyz = abc;
. В этом случае оба xyz
и abc
- это псевдонимы одного и того же объекта:
console.log(xyz === abc); // prints "true"
. Одной из основополагающих причин использования комбинированного стиля является атрибут «name» объектов функций (не поддерживаемый Internet & nbsp; Explorer). В основном, когда вы определяете функцию типа
function abc(){};
console.log(abc.name); // prints "abc"
, ее имя автоматически назначается. Но когда вы определяете его как
var abc = function(){};
console.log(abc.name); // prints ""
, его имя пуст & mdash; мы создали анонимную функцию и присвоили ей некоторую переменную.
Еще одна веская причина использовать комбинированный стиль - использовать короткое внутреннее имя для ссылки на себя, предоставляя длинное неконфликтное имя для внешних пользователей :
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
// Let it call itself recursively:
shortcut(n - 1);
// ...
// Let it pass itself as a callback:
someFunction(shortcut);
// ...
}
В приведенном выше примере мы можем сделать то же самое с внешним именем, но оно будет слишком громоздким (и медленнее).
(Другой способ ссылаться на себя - это использовать arguments.callee
, который все еще относительно длинный и не поддерживается в строгом режиме.)
Вниз, JavaScript обрабатывает оба утверждения по-разному. Это объявление функции:
function abc(){}
abc
здесь определено везде в текущей области:
// We can call it here
abc(); // Works
// Yet, it is defined down there.
function abc(){}
// We can call it again
abc(); // Works
Кроме того, он поднялся с помощью инструкции return
:
// We can call it here
abc(); // Works
return;
function abc(){}
Это выражение функции:
var xyz = function(){};
xyz
здесь определено из точки назначения:
// We can't call it here
xyz(); // UNDEFINED!!!
// Now it is defined
xyz = function(){}
// We can call it here
xyz(); // works
Объявление функции vs выражение функции является реальной причиной того, что существует разница, продемонстрированная Грегом.
Забавный факт:
var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"
Лично я предпочитаю декларацию «выражение функции», потому что таким образом я может контролировать видимость. Когда я определяю функцию, подобную
var abc = function(){};
, я знаю, что я определил функцию локально. Когда я определяю функцию, подобную
abc = function(){};
, я знаю, что я определил ее глобально, указав, что я не определял abc
где-либо в цепочке областей. Этот стиль определения устойчив даже при использовании внутри eval()
. Хотя определение
function abc(){};
зависит от контекста и может оставить вас гадать, где оно фактически определено, особенно в случае eval()
& mdash; ответ: это зависит от браузера.
О производительности:
Новые версии V8
ввели несколько оптимизаций под капотом, а также SpiderMonkey
.
почти нет разницы между выражением и декларацией. Функциональное выражение теперь работает быстрее .
Anonymous
функциональные выражения , по-видимому, имеют лучшую производительность по отношению кNamed
функциональному выражению.
Если вы будете использовать эти функции для создания объектов, вы получите:
var objectOne = new functionOne();
console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function
var objectTwo = new functionTwo();
console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function
console.log(objectOne.__proto__);
печатает & quot; functionOne {} & quot; в моей консоли. Любые идеи, почему это может быть так?
– Mike
22 March 2015 в 11:06
Это всего лишь два возможных способа объявления функций, а во втором - использование функции перед объявлением.
В терминах компьютерной науки мы говорим об анонимных функциях и названных функциях. Я думаю, что самое важное отличие состоит в том, что анонимная функция не связана с именем, отсюда и анонимная функция. В JavaScript это объект первого класса, динамически объявленный во время выполнения.
Для получения дополнительной информации об анонимных функциях и исчислении лямбда, Википедия - хорошее начало ( http://en.wikipedia.org/wiki /Anonymous_function).
var foo = function(){...}
даже для частных переменных.
– Sean McMillan
3 June 2011 в 13:32
function window.onload() {}
был чем-то.)
– Ry-♦
21 April 2013 в 20:42
Первый пример - это объявление функции:
function abc(){}
Второй пример - выражение функции:
var abc = function() {};
Основное различие заключается в том, как они поднимаются (поднимаются и объявлена). В первом примере объявляется объявление всей функции. Во втором примере поднимается только var 'abc', его значение (функция) будет неопределенным, а сама функция остается в том положении, в котором она объявлена.
Проще говоря:
//this will work
abc(param);
function abc(){}
//this would fail
abc(param);
var abc = function() {}
Чтобы узнать больше об этой теме, я настоятельно рекомендую вам эту ссылку
new Function()
может использоваться для передачи тела функции в строку. И, следовательно, это можно использовать для создания динамических функций. Также передайте скрипт без выполнения скрипта.
var func = new Function("x", "y", "return x*y;");
function secondFunction(){
var result;
result = func(10,20);
console.log ( result );
}
secondFunction()
Подъем - это действие интерпретатора JavaScript перемещения всех объявлений переменных и функций в верхнюю часть текущей области.
Однако, поднимаются только фактические декларации. оставляя присваивания там, где они есть.
Javascript называется свободно типизированным языком. Это означает, что переменные Javascript могут содержать значение любого Data-Type .
global_Page = 10; var global_Page; « undefined
« Integer literal, Number Type. ------------------- global_Page = 10; « Number
global_Page = 'Yash'; | Interpreted | global_Page = 'Yash'; « String
« String literal, String Type. « AS « global_Page = true; « Boolean
var global_Page = true; | | global_Page = function (){ « function
« Boolean Type ------------------- var local_functionblock; « undefined
global_Page = function (){ local_functionblock = 777;« Number
var local_functionblock = 777; };
// Assigning function as a data.
};
Функция
function Identifier_opt ( FormalParameterList_opt ) {
FunctionBody | sequence of statements
« return; Default undefined
« return 'some data';
}
Функция
function Identifier_opt ( FormalParameterList_opt ) {
FunctionBody | sequence of statements
« return; Default undefined
« return 'some data';
}
Scope with respect to function-block global.
Scope with respect to page undefined | not available.
Объявление функции
function globalAccess() { function globalAccess() {
} ------------------- }
globalAccess(); | | function globalAccess() { « Re-Defined / overridden.
localAccess(); « Hoisted As « function localAccess() {
function globalAccess() { | | }
localAccess(); ------------------- localAccess(); « function accessed with in globalAccess() only.
function localAccess() { }
} globalAccess();
} localAccess(); « ReferenceError as the function is not defined
Функция Expression
10; « literal
(10); « Expression (10).toString() -> '10'
var a;
a = 10; « Expression var a.toString() -> '10'
(function invoke() { « Expression Function
console.log('Self Invoking'); (function () {
}); }) () -> 'Self Invoking'
var f;
f = function (){ « Expression var Function
console.log('var Function'); f () -> 'var Function'
};
Функция, назначенная переменной Пример:
(function selfExecuting(){
console.log('IIFE - Immediately-Invoked Function Expression');
}());
var anonymous = function (){
console.log('anonymous function Expression');
};
var namedExpression = function for_InternalUSE(fact){
if(fact === 1){
return 1;
}
var localExpression = function(){
console.log('Local to the parent Function Scope');
};
globalExpression = function(){
console.log('creates a new global variable, then assigned this function.');
};
//return; //undefined.
return fact * for_InternalUSE( fact - 1);
};
namedExpression();
globalExpression();
javascript интерпретируется как
var anonymous;
var namedExpression;
var globalExpression;
anonymous = function (){
console.log('anonymous function Expression');
};
namedExpression = function for_InternalUSE(fact){
var localExpression;
if(fact === 1){
return 1;
}
localExpression = function(){
console.log('Local to the parent Function Scope');
};
globalExpression = function(){
console.log('creates a new global variable, then assigned this function.');
};
return fact * for_InternalUSE( fact - 1); // DEFAULT UNDEFINED.
};
namedExpression(10);
globalExpression();
Вы можете проверить декларацию функции, тест экспрессии на разных браузерах с помощью jsperf Test Runner
классов функций конструктора ES5 : объекты функций, созданные с использованием Function.prototype.bind
JavaScript рассматривает функции как объекты первого класса, поэтому, будучи объектом, вы можете назначить pro
function Shape(id) { // Function Declaration
this.id = id;
};
// Adding a prototyped method to a function.
Shape.prototype.getID = function () {
return this.id;
};
Shape.prototype.setID = function ( id ) {
this.id = id;
};
var expFn = Shape; // Function Expression
var funObj = new Shape( ); // Function Object
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 );
console.log( funObj.getID() ); // 10
ES6 введена функция стрелки: выражение функции стрелки имеет более короткий синтаксис, они лучше всего подходят для функций не-метода, и они не могут использоваться в качестве конструкторов.
ArrowFunction : ArrowParameters => ConciseBody
.const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd
Иллюстрация, когда нужно предпочесть первый метод ко второму, - это когда вам нужно избегать переопределения предыдущих определений функции.
С помощью
if (condition){
function myfunction(){
// Some code
}
}
это определение myfunction
переопределит любое предыдущее определение, так как оно будет выполнено во время синтаксического анализа.
Хотя
if (condition){
var myfunction = function (){
// Some code
}
}
выполняет правильную работу по определению myfunction
только тогда, когда condition
выполнено.
var myFunc = null;
вне цикла или вне блока if / elseif / else. Затем вы можете условно назначить разные функции одной и той же переменной. В JS лучше назначить отсутствующее значение null, а затем не определено. Поэтому сначала следует объявить myFunction как null, а затем назначить его позже, условно.
– Alexander Mills
26 May 2015 в 20:31
Ответ Грега достаточно хорош, но я все же хотел бы добавить что-то к нему, которое я узнал сейчас, наблюдая за видеороликами Дугласа Крокфорда Функциональное выражение: Оператор функции: Оператор функции является просто сокращением для оператора Таким образом, расширяется до , который расширяется дальше: И они оба подняты в верхнюю часть код. [/g2] var foo = function foo() {};
function foo() {};
var
с function
значением. function foo() {};
var foo = function foo() {};
var foo = undefined;
foo = function foo() {};
Оба являются разными способами определения функции. Разница заключается в том, как браузер интерпретирует и загружает их в контекст выполнения.
Первый случай - выражение функции, которое загружается только тогда, когда интерпретатор достигает этой строки кода. Поэтому, если вы сделаете это следующим образом, вы получите сообщение об ошибке, что functionOne не является функцией.
functionOne();
var functionOne = function() {
// Some code
};
Причина в том, что в первой строке не присваивается значение functionOne, и, следовательно, это не определено. Мы пытаемся назвать его как функцию, и, следовательно, получаем ошибку.
Во второй строке мы назначаем ссылку анонимной функции на функциюOne.
Вторая case - это объявления функций, которые загружаются до выполнения любого кода. Поэтому, если вы сделаете следующее, вы не получите никакой ошибки, поскольку объявление загружается до выполнения кода.
functionOne();
function functionOne() {
// Some code
}
Другие комментаторы уже рассмотрели семантическую разницу двух вариантов выше. Я хотел бы отметить стилистическую разницу: только вариация «назначение» может устанавливать свойство другого объекта.
Я часто создаю модули JavaScript с таким шаблоном:
(function(){
var exports = {};
function privateUtil() {
...
}
exports.publicUtil = function() {
...
};
return exports;
})();
С помощью этого шаблона ваши общедоступные функции будут использовать назначение, в то время как ваши частные функции используют объявление.
(обратите внимание также, что назначение должно содержать точку с запятой после инструкции, в то время как объявление запрещает ее.)
var foo = function(){...}
даже для частных переменных.
– Sean McMillan
3 June 2011 в 13:32
function window.onload() {}
был чем-то.)
– Ry-♦
21 April 2013 в 20:42
functionOne
- это просто переменная с назначенной ей анонимной функцией, тогда какfunctionTwo
- фактически именованная функция. Вызовите.toString()
на обоих, чтобы увидеть разницу. Это важно в некоторых случаях, когда вы хотите получить имя функции программно. – Jason Bunting 5 August 2011 в 22:18function expression
, второй -function declaration
. Вы можете прочитать больше по этой теме: javascriptweblog.wordpress.com/2010/07/06/… – Michal Kuklis 14 November 2011 в 08:03