Скрытые функции JavaScript? [закрытый]

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

312
задан 11 revs, 6 users 36% 23 May 2017 в 02:10
поделиться

99 ответов

Синтаксический сахар: встройте закрытия для цикла

var i;

for (i = 0; i < 10; i++) (function ()
{
    // do something with i
}());

Повреждения почти все конвенции кода Douglas Crockford, но я думаю, что довольно хорошо посмотреть на, однако:)

<час>

Альтернатива:

var i;

for (i = 0; i < 10; i++) (function (j)
{
    // do something with j
}(i));
3
ответ дан 3 revs, 2 users 55% 23 November 2019 в 01:10
поделиться

Joose является хорошей объектной системой, если Вы хотели бы Основанное на классах OO, которое чувствует несколько как CLOS.

// Create a class called Point
Class("Point", {
    has: {
        x: {
            is:   "rw",
            init: 0
        },
        y: {
            is:   "rw",
            init: 0
        }
    },
    methods: {
        clear: function () {
            this.setX(0);
            this.setY(0);
        }
    }
})

// Use the class
var point = new Point();
point.setX(10)
point.setY(20);
point.clear();
3
ответ дан jrockway 23 November 2019 в 01:10
поделиться

Большие циклы быстрее в while - условие и назад - то есть, если порядок цикла не имеет значения для Вас. Приблизительно в 50% моего кода это обычно не делает.

т.е.

var i, len = 100000;

for (var i = 0; i < len; i++) {
  // do stuff
}

медленнее, чем:

i = len;
while (i--) {
  // do stuff
}
4
ответ дан 2 revs, 2 users 97% 23 November 2019 в 01:10
поделиться

Удивительно, сколько людей не понимает, что это объектно-ориентировано также.

4
ответ дан 2 revs, 2 users 50% 23 November 2019 в 01:10
поделиться

jQuery и JavaScript:

Имена переменной могут содержать много нечетных символов. Я использую символ $ для идентификации переменных, содержащих объекты jQuery:

var $links = $("a");

$links.hide();

шаблон jQuery объединения в цепочку объектов довольно хорош, но применение этого шаблона может стать немного сбивающим с толку. К счастью, JavaScript позволяет Вам повреждать строки, как так:

$("a")
.hide()
.fadeIn()
.fadeOut()
.hide();

Общий JavaScript:

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

function test()
{
    // scope of test()

    (function()
    {
        // scope inside the scope of test()
    }());

    // scope of test()
}
4
ответ дан cllpse 23 November 2019 в 01:10
поделиться

Все Ваши "скрытые" функции находятся прямо здесь на Wiki Mozilla: http://developer.mozilla.org/en/JavaScript .

существует базовая ссылка JavaScript 1.5 , новые функции и возможности в JavaScript 1.6, что является новое в JavaScript 1.7, и также что является новое в JavaScript 1.8. Просмотрите всех тех для примеров, которые на самом деле работают и являются не неправильно.

5
ответ дан 2 revs, 2 users 95% 23 November 2019 в 01:10
поделиться

Этот супер скрыт, и только иногда полезный;-)

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

var o1 = { foo: 1, bar: 'abc' };
function f() {}
f.prototype = o1;
o2 = new f();
assert( o2.foo === 1 );
assert( o2.bar === 'abc' );
o2.foo = 2;
o2.baz = true;
assert( o2.foo === 2 );
// o1 is unchanged by assignment to o2
assert( o1.foo === 1 );
assert( o2.baz );

Это только покрывает 'простые' значения на o1. Если Вы изменяете массив или другой объект, то прототип больше не 'защищает' исходный объект. Остерегайтесь каждый раз, когда Вы имеете {} или [] в Определении класса / прототип.

5
ответ дан noah 23 November 2019 в 01:10
поделиться

undefined не определено. Таким образом, можно сделать это:

if (obj.field === undefined) /* ... */
6
ответ дан 2 revs, 2 users 80% 23 November 2019 в 01:10
поделиться

Посещение:

Вставка этот код JavaScript в строку поиска Вашего веб-браузера:

Обладает выставочным:-p

дискотеки JavaScript
6
ответ дан 2 revs, 2 users 86% 23 November 2019 в 01:10
поделиться

Генераторы и Итераторы (работает только в Firefox 2 + и Safari).

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i < 10; i++) {
  document.write(g.next() + "<br>\n");
}

функция, содержащая yield, ключевое слово является генератором. При вызове его его формальные параметры связываются с действительными аргументами, но его тело на самом деле не оценено. Вместо этого итератор генератора возвращается. Каждый вызов к итератору генератора next() метод работает, другой проходит через итеративный алгоритм. Значение каждого шага является значением, определенным yield ключевое слово. Думайте yield как версия итератора генератора возврата, указывая на границу между каждым повторением алгоритма. Каждый раз Вы звоните next(), резюме кода генератора от оператора после yield.

В нормальном использовании, объекты итератора "невидимы"; Вы не должны будете воздействовать на них явно, но будете вместо этого использовать JavaScript for...in и for each...in операторы для цикличного выполнения естественно по ключам и/или значениям объектов.

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  document.write(objectWithIterator[i] + "<br>\n");
}
6
ответ дан Eugene Yokota 23 November 2019 в 01:10
поделиться

Function.toString () (неявный):

function x() {
    alert("Hello World");
}
eval ("x = " + (x + "").replace(
    'Hello World',
    'STACK OVERFLOW BWAHAHA"); x("'));
x();
7
ответ дан 2 revs, 2 users 94% 23 November 2019 в 01:10
поделиться

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

А несколько менее опасная форма этого является добавлением вспомогательных методов для существующих объектов. Вы можете заставлять IE6 "исходно" поддерживать indexOf на массивах , например.

1
ответ дан treat your mods well 23 November 2019 в 01:10
поделиться

Для преобразования числа с плавающей точкой в целое число можно использовать один из следующих загадочных взломов (не делайте):

  1. 3.14 >> 0 (через 2,9999999999999999 > >.5? )
  2. 3.14 | 0 (через , Что лучший метод должен преобразовать плавающую точку в целое число в JavaScript? )
  3. 3.14 & -1
  4. 3.14 ^ 0
  5. ~~3.14

В основном, применяя любую бинарную операцию на плавание, которое не изменит окончательное значение (т.е. тождественное отображение) заканчивает тем, что преобразовал плавание в целое число.

2
ответ дан 3 revs, 2 users 82% 23 November 2019 в 01:10
поделиться

Это, кажется, только работает над Firefox (SpiderMonkey). В функции:

  • arguments[-2] дает количество аргументов (то же как arguments.length)
  • arguments[-3] дает функцию, которая была вызвана (то же как arguments.callee)
2
ответ дан 2 revs 23 November 2019 в 01:10
поделиться

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

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

Вот пример моего старого "одноэлементного" подхода:

var singleton = function(){ 

  if (typeof arguments.callee.__instance__ == 'undefined') { 

    arguments.callee.__instance__ = new function(){

      //this creates a random private variable.
      //this could be a complicated calculation or DOM traversing that takes long
      //or anything that needs to be "cached"
      var rnd = Math.random();

      //just a "public" function showing the private variable value
      this.smth = function(){ alert('it is an object with a rand num=' + rnd); };

   };

  }

  return arguments.callee.__instance__;

};


var a = new singleton;
var b = new singleton;

a.smth(); 
b.smth();

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

, Например, я использовал этот подход назад в 2004, когда я должен был создать модальное диалоговое окно с серым фоном, который покрыл целую страницу (что-то как Лайтбокс ). Internet Explorer 5.5 и 6 имеет самый высокий контекст укладки для < select> или < iframe> элементы из-за их "оконного" характера; таким образом, если страница содержавшие избранные элементы, единственный способ покрыть их состоял в том, чтобы создать iframe и расположить ее "на вершину" страницы. Таким образом, целый сценарий был довольно сложным и немного медленным (он использовал фильтр: выражения для установки непрозрачности для покрытия iframe). Сценарий "контейнера" имел только один ".show ()" метод, который создал контейнер только однажды и кэшировал его в статической переменной:)

2
ответ дан 2 revs, 2 users 84% 23 November 2019 в 01:10
поделиться

Существует также почти неизвестный синтаксис JavaScript:

var a;
a=alert(5),7;
alert(a);    // alerts undefined
a=7,alert(5);
alert(a);    // alerts 7

a=(3,6);
alert(a);    // alerts 6
[еще 113] об этом здесь .

2
ответ дан 3 revs, 2 users 84% 23 November 2019 в 01:10
поделиться

Проверки существования. Так часто я вижу материал как это

var a = [0, 1, 2];

// code that might clear the array.

if (a.length > 0) {
 // do something
}

вместо этого, например, просто сделайте это:

var a = [0, 1, 2];

// code that might clear the array.

if (a.length) { // if length is not equal to 0, this will be true
 // do something
}

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

Вот пример о том, как использовать значение по умолчанию.

function (someArgument) {
      someArgument || (someArgument = "This is the deault value");
}

Это составляет мои два цента. Существуют другие самородки, но вот именно на данный момент.

3
ответ дан 2 revs, 2 users 97% 23 November 2019 в 01:10
поделиться

Вы можете перебирать массивы, используя «for in»

Марк Сидаде указал на полезность «for in» "loop:

// creating an object (the short way, to use it like a hashmap)
var diner = {
"fruit":"apple"
"veggetable"="bean"
}

// looping over its properties
for (meal_name in diner ) {
    document.write(meal_name+"<br \n>");
}

Результат:

fruit
veggetable

Но это еще не все. Поскольку вы можете использовать объект, такой как ассоциативный массив, вы можете обрабатывать ключи и значения, точно так же, как цикл foreach:

// looping over its properties and values
for (meal_name in diner ) {
    document.write(meal_name+" : "+diner[meal_name]+"<br \n>");
}

Результат:

fruit : apple
veggetable : bean

И так как массивы также являются объектами, вы можете выполнять итерации другого массива точно таким же образом:

var my_array = ['a', 'b', 'c'];
for (index in my_array ) {
    document.write(index+" : "+my_array[index]+"<br \n>");
}

Результат:

0 : a
1 : b
3 : c

Вы можете легко удалить известный элемент из массива

var arr = ['a', 'b', 'c', 'd'];
var pos = arr.indexOf('c');
pos > -1 && arr.splice( pos, 1 );

Вы можете легко перемешать массив

arr.sort (function () Math.random () - 0.5); - не совсем случайное распределение, см. Комментарии.

3
ответ дан 2 revs, 2 users 99% 23 November 2019 в 01:10
поделиться

Maybe one of the lesser-known ones:

arguments.callee.caller + Function#toString()

function called(){
    alert("Go called by:\n"+arguments.callee.caller.toString());
}

function iDoTheCall(){
    called();
}

iDoTheCall();

Prints out the source code of iDoTheCall -- Deprecated, but can be useful sometimes when alerting is your only option....

2
ответ дан 23 November 2019 в 01:10
поделиться
1
ответ дан 23 November 2019 в 01:10
поделиться

Оператор объединения очень крутой и позволяет получить чистый и лаконичный код, особенно когда вы объединяете его в цепочку: a || б || c || "default"; Загвоздка в том, что, поскольку он работает, вычисляя значение bool, а не null, если значения, которые оцениваются как false, являются допустимыми, они часто будут игнорироваться. Не волнуйтесь, в этих случаях просто вернитесь к старому доброму тернарному оператору.

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

var getInstance = function(objectName) {
  if ( !getInstance.instances ) {
    getInstance.instances = {};
  }

  if ( !getInstance.instances[objectName] ) {
    getInstance.instances[objectName] = new window[objectName];
  }

  return getInstance.instances[objectName];
};

Также обратите внимание на new window [objectName]; , который был ключом к универсальному созданию экземпляров объектов по имени. Я понял это только 2 месяца назад.

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

Удивительно, но никто на первой странице не упомянул hasOwnProperty , что очень досадно. При использовании в для итерации, это хорошее защитное программирование - использовать метод hasOwnProperty в контейнере, для которого выполняется итерация, чтобы убедиться, что используемые имена членов соответствуют ожидаемым.

var x = [1,2,3];
for ( i in x ) {
    if ( !x.hasOwnProperty(i) )  { continue; }
    console.log(i, x[i]);
}

Подробнее об этом читайте здесь .

Наконец, с почти всегда плохая идея.

никто на первой странице не упомянул hasOwnProperty , что очень досадно. При использовании в для итерации, это хорошее защитное программирование - использовать метод hasOwnProperty в контейнере, для которого выполняется итерация, чтобы убедиться, что используемые имена членов соответствуют ожидаемым.

var x = [1,2,3];
for ( i in x ) {
    if ( !x.hasOwnProperty(i) )  { continue; }
    console.log(i, x[i]);
}

Подробнее об этом читайте здесь .

Наконец, с почти всегда плохая идея.

никто на первой странице не упомянул hasOwnProperty , что очень досадно. При использовании в для итерации, это хорошее защитное программирование - использовать метод hasOwnProperty в контейнере, для которого выполняется итерация, чтобы убедиться, что используемые имена членов соответствуют ожидаемым.

var x = [1,2,3];
for ( i in x ) {
    if ( !x.hasOwnProperty(i) )  { continue; }
    console.log(i, x[i]);
}

Подробнее об этом читайте здесь .

Наконец, с почти всегда плохая идея.

1
ответ дан 23 November 2019 в 01:10
поделиться

Вы можете создать «классы», которые имеют частные (недоступные вне определения «класса») статические и нестатические члены, в дополнение к открытым членам. , используя замыкания.

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

var MyClass = (function () {
    // private static
    var nextId = 1;

    // constructor
    var cls = function () {
        // private
        var id = nextId++;
        var name = 'Unknown';

        // public (this instance only)
        this.get_id = function () { return id; };

        this.get_name = function () { return name; };
        this.set_name = function (value) {
            if (typeof value != 'string')
                throw 'Name must be a string';
            if (value.length < 2 || value.length > 20)
                throw 'Name must be 2-20 characters long.';
            name = value;
        };
    };

    // public static
    cls.get_nextId = function () {
        return nextId;
    };

    // public (shared across instances)
    cls.prototype = {
        announce: function () {
            alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
                  'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
        }
    };

    return cls;
})();

Чтобы проверить этот код:

var mc1 = new MyClass();
mc1.set_name('Bob');

var mc2 = new MyClass();
mc2.set_name('Anne');

mc1.announce();
mc2.announce();

Если у вас есть Firebug, вы обнаружите, что нет другого способа получить доступ к закрытым членам, кроме как установить точку останова внутри замыкания, которое их определяет.

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

Чтобы расширить этот класс, вы должны поместить MyClass.call (this); вверху конструктора в расширяющемся классе. Вам также потребуется скопировать объект MyClass.prototype (не используйте его повторно, так как вы также измените члены MyClass .

Если бы вы заменили метод announce , вы бы вызывали из него MyClass.announce следующим образом: MyClass.prototype.announce.call (this);

1
ответ дан 23 November 2019 в 01:10
поделиться

JavaScript typeof operator used with arrays or nulls always returns object value which in some cases may not be what programmer would expect.

Here's a function that will return proper values for those items as well. Array recognition was copied from Douglas Crockford's book "JavaScript: The Good Parts".

function typeOf (value) {
    var type = typeof value;
    if (type === 'object') {
        if (value === null) {
             type = 'null';
        } else if (typeof value.length === 'number' && 
            typeof value.splice === 'function' && 
            !value.propertyIsEnumerable('length')) {
            type = 'array';
        }
    }
    return type;
}
3
ответ дан 23 November 2019 в 01:10
поделиться

Использование Function.apply для указания объекта, над которым будет работать функция:

Предположим, у вас есть класс

function myClass(){
 this.fun = function(){
   do something;
 };
}

, если позже вы сделаете:

var a = new myClass();
var b = new myClass();

myClass.fun.apply(b); //this will be like b.fun();

Вы даже можете указать массив параметров вызова в качестве второго аргумента

, посмотрите это: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/apply

1
ответ дан 23 November 2019 в 01:10
поделиться

Пространства имен

В больших приложениях или платформах JavaScript может быть полезно организовать код в пространствах имен. В JavaScript нет встроенного модуля или концепции пространства имен, но его легко эмулировать с помощью объектов JavaScript. Это создаст пространство имен ns и присоединит к нему функцию foo .

if (!window.ns) {
  window.ns = {};
}

window.ns.foo = function() {};

Обычно используется один и тот же префикс глобального пространства имен во всем проекте и подпространства имен для каждого JavaScript. файл. Имя подпространства имен часто совпадает с именем файла.

Заголовок файла с именем ns / button.js может выглядеть следующим образом:

if (!window.ns) {
  window.ns = {};
}
if (!window.ns.button) {
  window.ns.button = {};
}

// attach methods to the ns.button namespace
window.ns.button.create = function() {};
5
ответ дан 23 November 2019 в 01:10
поделиться

Это не всегда хорошая идея, но вы можете преобразовать большинство вещей с помощью кратких выражений. Важным моментом здесь является то, что не каждое значение в JavaScript является объектом, поэтому эти выражения будут успешными, если доступ к членам не-объектов, таких как null и undefined, завершится ошибкой. В частности, остерегайтесь этого typeof null == "object", но вы не можете null.toString () или ("name" в null).

Преобразование чего-либо в число:

+anything
Number(anything)

Преобразование чего-либо в беззнаковое четыре -байтное целое число:

anything >>> 0

Преобразование чего-либо в строку:

'' + anything
String(anything)

Преобразование чего-либо в логическое значение:

!!anything
Boolean(anything)

Кроме того, использование имени типа без «нового» ведет себя по-разному для String, Number и Boolean, возвращая примитивное число, строка или логическое значение, но с "новым" они будут возвращать "упакованные" типы объектов,

4
ответ дан 23 November 2019 в 01:10
поделиться

Хм, я не прочитал всю тему, хотя для меня это довольно интересно, но позвольте мне сделать небольшое пожертвование:

// forget the debug alerts
var alertToFirebugConsole = function() {
    if ( window.console && window.console.log ) {
        window.alert = console.log;
    }
}
2
ответ дан 23 November 2019 в 01:10
поделиться

JavaScript считается очень хорошим при разоблачении всего его объекта, поэтому независимо от того, если его окно объекта.

Итак, если я хотел бы переопределить предупреждение браузера с всплывающим окном jQuery / Yui Div, который также принимает строку в качестве параметра, можно сделать, просто используя следующий фрагмент.


function divPopup(str)
{
    //code to show the divPopup
}
window.alert = divPopup;

При этом изменение всех вызовов на оповещение () покажет хорошее новое всплывающее окно на основе div вместо предупреждения о конкретном браузере.

2
ответ дан 23 November 2019 в 01:10
поделиться

Разреженные проверки теперь в Git 1,7 .

См. также вопрос « Можно ли выполнить разреженную проверку без предварительной проверки всего хранилища? ».

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

-121--1819844-

Постоянно ссылайтесь на стандарты POSIX для любых используемых библиотечных функций. Части стандарта неоднозначны, и некоторые системы возвращают различные стили кодов ошибок. Это поможет вам упреждающе находить тех, кому действительно трудно найти несколько другие ошибки реализации.

-121--2434767-

Универсальность JavaScript - Переопределение функциональности по умолчанию


Вот код переопределения функции window.alert с виджетом диалогового окна интерфейса jQuery. Я сделал это как подключаемый модуль jQuery. И вы можете прочитать об этом в моем блоге; altAlert, подключаемый модуль jQuery для персонализированных предупреждающих сообщений .

jQuery.altAlert = function (options)  
{  
    var defaults = {  
        title: "Alert",  
        buttons: {  
            "Ok": function()  
            {  
                jQuery(this).dialog("close");  
            }  
        }  
    };  

    jQuery.extend(defaults, options);  

    delete defaults.autoOpen;  

    window.alert = function ()  
    {  
        jQuery("<div />", {
            html: arguments[0].replace(/\n/, "<br />")
        }).dialog(defaults);  
    };  
};
2
ответ дан 23 November 2019 в 01:10
поделиться

Это скрытая особенность jQuery, а не Javascript, но поскольку вопроса "скрытые особенности jQuery" никогда не будет...

В jQuery можно определить свои собственные селекторы :something:

$.extend($.expr[':'], {
  foo: function(node, index, args, stack) {
    // decide if selectors matches node, return true or false
  }
});

Для селекторов, использующих :foo, таких как $('div.block:foo("bar,baz") span'), функция foo будет вызвана для всех узлов, которые соответствуют уже обработанной части селектора. Значение аргументов:

  • node содержит текущий узел
  • index - индекс узла в наборе узлов
  • args - массив, который полезен, если селектор имеет аргумент или несколько имен:
    • args[0] - весь текст селектора (например, :foo("bar, baz"))
    • args[1] - имя селектора (например, foo)
    • args[2] - символ кавычки, используемый для обертывания аргумента. (например, " для :foo("bar, baz")) или пустая строка, если кавычки не используются (:foo(bar, baz)) или неопределено, если нет аргумента
    • args[3] - аргумент, включая любые кавычки (например, "bar, baz") или undefined, если аргументов нет
  • stack - набор узлов (массив, содержащий все узлы, которые совпали в данный момент)

Функция должна возвращать true, если селектор совпадает, false в противном случае.

Например, следующий код позволит выбирать узлы на основе полнотекстового регекспового поиска:

$.extend($.expr[':'], {
  matches: function(node, index, args, stack) {
    if (!args.re) { // args is a good place for caching
      var re = args[3];
      if (args[2]) { // get rid of quotes
        re = re.slice(1,-1);
      }
      var separator = re[0];
      var pos = re.lastIndexOf(separator);
      var modifiers = re.substr(pos+1);
      var code = re.substr(1, pos-1);
      args.re = new RegExp(code, modifiers);
    }
    return $(node).text().match(args.re);
  }
});

// find the answers on this page which contain /**/-style comments
$('.answer .post-text code:matches(!/\\*[\\s\\S]*\\*/!)');

Вы могли бы достичь подобного эффекта с помощью callback-версии .filter(), но пользовательские селекторы гораздо более гибкие и обычно более читаемые.

7
ответ дан 23 November 2019 в 01:10
поделиться