Передача аргументов функции в JavaScript аналогична передаче параметров по значению указателя в C:
/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.
function changeStuff(num, obj1, obj2)
{
num = num * 10;
obj1.item = "changed";
obj2 = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
This produces the output:
10
changed
unchanged
*/
#include <stdio.h>
#include <stdlib.h>
struct obj {
char *item;
};
void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
// make pointer point to a new memory location
// holding the new integer value
int *old_num = num;
num = malloc(sizeof(int));
*num = *old_num * 10;
// make property of structure pointed to by pointer
// point to the new value
obj1->item = "changed";
// make pointer point to a new memory location
// holding the new structure value
obj2 = malloc(sizeof(struct obj));
obj2->item = "changed";
free(num); // end of scope
free(obj2); // end of scope
}
int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };
int main()
{
// pass pointers by value: the pointers
// will be copied into the argument list
// of the called function and the copied
// pointers will point to the same values
// as the original pointers
changeStuff(&num, &obj1, &obj2);
printf("%d\n", num);
puts(obj1.item);
puts(obj2.item);
return 0;
}
Синтаксис JavaScript 101. Вот объявление функции:
function foo() {}
Обратите внимание, что нет точки с запятой: это просто объявление функции. Вам понадобится вызов foo()
, чтобы фактически запустить функцию.
Теперь, когда мы добавляем кажущуюся безобидную восклицательную знак: !function foo() {}
, она превращает ее в выражение. В настоящее время это выражение функции.
Конечно, !
не вызывает функцию, но мы можем теперь положить ()
в конец: !function foo() {}()
, который имеет более высокий приоритет, чем !
и мгновенно вызывает функцию.
Так что автор делает сохранение байта на выражение функции; более читаемым способом его написания было бы следующее:
(function(){})();
Наконец, !
возвращает выражение true. Это связано с тем, что по умолчанию все возвраты IIFE undefined
, что оставляет нас с !undefined
, который является true
. Не особенно полезно.
!
будет отрицать (противоположно) то, что вы ожидаете в результате, т. е. если вы
var boy = true;
undefined
boy
true
!boy
false
, когда вы вызываете boy
, ваш результат будет true
, но в момент добавления !
при вызове boy
, т. е. !boy
, ваш результат будет false
. Иными словами, вы имеете в виду NotBoy, но на этот раз это в основном логический результат: true
или false
.
Это то же самое, что происходит с выражением !function () {}();
, работающим только function () {}();
отметит вам ошибку, но добавит !
прямо перед вашим выражением function () {}();
, делает ее противоположной function () {}();
, которая должна вернуть вас true
. Пример можно увидеть ниже:
function () {}();
SyntaxError: function statement requires a name
!function () {}();
true
Функция:
function () {}
ничего не возвращает (или не определена).
Иногда мы хотим вызвать функцию справа, когда мы ее создаем. У вас может возникнуть соблазн попробовать следующее:
function () {}()
, но это приводит к SyntaxError
.
Используя оператор !
до того, как функция заставит его рассматривать как выражение, поэтому мы можем назвать его:
!function () {}()
Это также возвращает логическое значение, противоположное возвращаемому значению функции, в данном случае true
, поскольку !undefined
- true
. Если вы хотите, чтобы фактическое возвращаемое значение являлось результатом вызова, попробуйте сделать это следующим образом:
(function () {})()
!
- превратить объявление функции в выражение функции, вот и все.
– Skilldrick
30 September 2011 в 09:28
Существует хорошая точка для использования !
для вызова функции, отмеченного на airbnb JavaScript guide
В общем, идея использования этого метода в отдельных файлах (ака модули), которые позже получают сцепляются. Предостережение здесь состоит в том, что файлы должны быть объединены инструментами, которые помещают новый файл в новую строку (что в любом случае является обычным для большинства инструментов concat). В этом случае использование !
поможет избежать ошибки в том случае, если ранее конкатенированный модуль пропустил конечную точку с запятой, и все же это даст гибкость, чтобы поместить их в любом порядке, не беспокоясь.
!function abc(){}()
!function bca(){}();
Будет работать одинаково как
!function abc(){}()
;(function bca(){})();
, но сохраняет два символа и произвольно выглядит лучше.
И, кстати, любой из операторов +
, -
, ~
, void
имеет тот же эффект, с точки зрения вызывающей функции, наверняка, если вы используете что-то для возврата из этой функции, они будут действовать по-другому.
abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?
, но если вы используете шаблоны IIFE для одного файла, разделите код модуля и используя инструмент concat для оптимизации (что делает однострочное одно файлное задание), чем конструкция
!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()
Выполняет безопасное выполнение кода, то же самое, что и в самом первом примере кода.
Это вызовет ошибку. JavaScript ASI не сможет выполнить свою работу.
!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()
Одна нота относительно унарных операторов, они будут выполнять аналогичную работу, но только в случае они не использовались в первом модуле. Таким образом, они не настолько безопасны, если у вас нет полного контроля над порядком конкатенации.
Это работает:
!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()
Это не:
^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()
И вот что-то большее, что я понял из консоли. Как упоминалось ранее, восклицательный знак заставляет функцию возвращать логическое значение.
Для последнего синтаксиса:
( function my_function() {} )()
Мы можем сделать что-то вроде:
(function add_them(a,b) { return a+b;} )(9,4)
Как одновременное определение функции и вызов.
Редактирование: теперь вы спросите, в чем польза '!' определение функции типа. Давайте рассмотрим следующее:
!function a_would_be_function() { alert("Do some junk but inside a function"); }()
вы хотели бы выполнить такую функцию, как указано выше, но без '!' будет генерировать ошибку. Надеюсь, я понятен.
Его другой способ записи IIFE (непосредственное выражение функции).
Другой способ записи -
(function( args ) {})()
, такой же, как
!function ( args ) {}();
jQuery("#btn").on('click', function() {
var $txt = jQuery("#txt");
var caretPos = $txt[0].selectionStart;
var textAreaTxt = $txt.val();
var txtToAdd = "stuff";
$txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
});
и оставил бы эту форму <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />
инструментам минимизации и запутывания.
– Tobias
16 October 2017 в 14:31
Он возвращает, может ли оператор оценивать значение false. например:
!false // true
!true // false
!isValid() // is not valid
Вы можете использовать его дважды, чтобы принудить значение к boolean:
!!1 // true
!!0 // false
Итак, чтобы более точно ответить на ваш вопрос:
var myVar = !function(){ return false; }(); // myVar contains true
Редактировать: он имеет побочный эффект изменения объявления функции в выражении функции. Например. следующий код недействителен, поскольку он интерпретируется как объявление функции, в котором отсутствует требуемый идентификатор (или имя функции ):
function () { return false; }(); // syntax error
var myVar = !function(){ return false; }()
может опустить !
как var myVar = function(){ return false; }()
, и функция будет выполнена правильно, а возвращаемое значение будет не тронуто.
– Mark Fox
11 March 2013 в 02:55
true
на !0
и false
на !1
. Он сохраняет 2 или 3 символа.
– Triynko
26 July 2015 в 01:07
! является логическим оператором NOT, это логический оператор, который будет инвертировать что-то противоположное.
Хотя вы можете обойти круглые скобки вызываемой функции, используя функцию BANG (!) перед функцией, она все равно инвертирует возврат, который может быть не таким, каким вы хотели. Как и в случае с IEFE, он возвращает undefined , который при инвертировании становится логическим значением true.
Вместо этого используйте закрывающую скобку и BANG (!) если нужно.
blockquote>// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening. (function(){ return false; }()); => false !(function(){ return false; }()); => true !!(function(){ return false; }()); => false !!!(function(){ return false; }()); => true
Другие операторы, которые работают ...
blockquote>+(function(){ return false; }()); => 0 -(function(){ return false; }()); => -0 ~(function(){ return false; }()); => -1
Комбинированные операторы ...
blockquote>+!(function(){ return false; }()); => 1 -!(function(){ return false; }()); => -1 !+(function(){ return false; }()); => true !-(function(){ return false; }()); => true ~!(function(){ return false; }()); => -2 ~!!(function(){ return false; }()); => -1 +~(function(){ return false; }()); +> -1
Сохраним несколько других байтов!
(() => {})()
пример:
(() => {return "yeah"})()
рассмотрим нижеприведенную анонимную функцию
let stateObject = { foo: "bar" };
history.pushState(stateObject, "page 2", "newpage.html");
[g2] Чтобы сделать вышеупомянутую функцию самопризываемой, мы обычно будем измените приведенный выше код на [/g2] [f2] [g3] Теперь мы добавили два дополнительных символа [f4], кроме добавления [f5] в конце функции, которая необходима для вызова функции. В процессе минификации мы обычно фокусируемся на уменьшении размера файла. Таким образом, мы можем также написать вышеупомянутую функцию как [/g3] [f3] [g4]. Тем не менее, обе они являются функциями, вызывающими себя, и мы также сохраняем байт. Вместо 2 символов [f6] мы просто использовали один символ [f7] [/g4]
!
возвращает логическое значение, мы все это знаем, но самое важное, что вы делаете, это то, что он также преобразует оператор объявления функции в выражение функции, так что функция может быть немедленно вызвана без ее обертывания в круглых скобках. Не очевидна и явно цель кодера. – gilly3 28 July 2011 в 17:58var foo =
нарушает двусмысленность оператора / выражения, и вы можете просто написатьvar foo = function(bar){}("baz");
и т. Д. – Neil 8 October 2013 в 11:49