Существует три примечательных сравнения между двумя различными декларациями функций, перечисленными ниже.
Выполняется следующее, поскольку 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;
}
})();
На основании this thread
и того, что там указано Томаса Мюллера , вы можете определить типы с теми же сигнатурами, что и методы, адреса которых вы хотите получить (для каждой перегрузки) , Если вы затем объявите переменные этих типов и назначите им указатели на объекты, вы убедитесь, что компилятор выбирает правильную перегрузку для вашего известного типа переменной и, кроме того, что она не будет игнорировать их, если они не будут использоваться нигде в коде (некоторые перегрузки не могут быть связаны в вашем двоичном коде).
Поэтому, основываясь на его идее, он может искать перегрузку функции MessageDlgPosHelp
следующим образом:
type
TMessageDlgPosHelp1 = function(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer;
const HelpFileName: string): Integer;
TMessageDlgPosHelp2 = function(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer;
const HelpFileName: string; DefaultButton: TMsgDlgBtn): Integer;
procedure TForm1.Button1Click(Sender: TObject);
var
MessageDlgPosHelp1: TMessageDlgPosHelp1;
MessageDlgPosHelp2: TMessageDlgPosHelp2;
begin
MessageDlgPosHelp1 := MessageDlgPosHelp;
MessageDlgPosHelp2 := MessageDlgPosHelp;
ShowMessage(Format('%p; %p', [@MessageDlgPosHelp1, @MessageDlgPosHelp2]));
end;
Также вы можете создать производный класс, который будет раскрывать эти методы перегрузки как простые методы с разными именами, отбрасывать любой экземпляр этого класса в новый класс и легко использовать адрес ваших методов-оберток.