Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Синтаксический сахар: встройте закрытия для цикла
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));
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();
Большие циклы быстрее в while
- условие и назад - то есть, если порядок цикла не имеет значения для Вас. Приблизительно в 50% моего кода это обычно не делает.
т.е.
var i, len = 100000;
for (var i = 0; i < len; i++) {
// do stuff
}
медленнее, чем:
i = len;
while (i--) {
// do stuff
}
Удивительно, сколько людей не понимает, что это объектно-ориентировано также.
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()
}
Все Ваши "скрытые" функции находятся прямо здесь на Wiki Mozilla: http://developer.mozilla.org/en/JavaScript .
существует базовая ссылка JavaScript 1.5 , новые функции и возможности в JavaScript 1.6, что является новое в JavaScript 1.7, и также что является новое в JavaScript 1.8. Просмотрите всех тех для примеров, которые на самом деле работают и являются не неправильно.
Этот супер скрыт, и только иногда полезный;-)
можно использовать цепочку прототипа для создания объекта, который делегирует к другому объекту, не изменяя исходный объект.
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. Если Вы изменяете массив или другой объект, то прототип больше не 'защищает' исходный объект. Остерегайтесь каждый раз, когда Вы имеете {} или [] в Определении класса / прототип.
undefined
не определено. Таким образом, можно сделать это:
if (obj.field === undefined) /* ... */
Посещение:
Вставка этот код JavaScript в строку поиска Вашего веб-браузера:
Обладает выставочным:-p
дискотеки JavaScriptГенераторы и Итераторы (работает только в 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");
}
Function.toString () (неявный):
function x() {
alert("Hello World");
}
eval ("x = " + (x + "").replace(
'Hello World',
'STACK OVERFLOW BWAHAHA"); x("'));
x();
Можно переопределить значительные части среды выполнения на лету, такой как изменение Array
конструктор или определение undefined
. Не то, чтобы Вы должны, но это может быть мощной функцией.
А несколько менее опасная форма этого является добавлением вспомогательных методов для существующих объектов. Вы можете заставлять IE6 "исходно" поддерживать indexOf на массивах , например.
Для преобразования числа с плавающей точкой в целое число можно использовать один из следующих загадочных взломов (не делайте):
3.14 >> 0
(через 2,9999999999999999 > >.5? ) 3.14 | 0
(через , Что лучший метод должен преобразовать плавающую точку в целое число в JavaScript? ) 3.14 & -1
3.14 ^ 0
~~3.14
В основном, применяя любую бинарную операцию на плавание, которое не изменит окончательное значение (т.е. тождественное отображение) заканчивает тем, что преобразовал плавание в целое число.
Это, кажется, только работает над Firefox (SpiderMonkey). В функции:
arguments[-2]
дает количество аргументов (то же как arguments.length
) arguments[-3]
дает функцию, которая была вызвана (то же как arguments.callee
) Как 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 ()" метод, который создал контейнер только однажды и кэшировал его в статической переменной:)
Существует также почти неизвестный синтаксис 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] об этом здесь .
Проверки существования. Так часто я вижу материал как это
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");
}
Это составляет мои два цента. Существуют другие самородки, но вот именно на данный момент.
Марк Сидаде указал на полезность «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);
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....
Оператор объединения очень крутой и позволяет получить чистый и лаконичный код, особенно когда вы объединяете его в цепочку: 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]);
}
Подробнее об этом читайте здесь .
Наконец, с
почти всегда плохая идея.
Вы можете создать «классы», которые имеют частные (недоступные вне определения «класса») статические и нестатические члены, в дополнение к открытым членам. , используя замыкания.
Обратите внимание, что в приведенном ниже коде есть два типа открытых членов. Зависящие от экземпляра (определенные в конструкторе), у которых есть доступ к частным членам экземпляра и разделяемым членам (определенным в объекте прототипа ), которые имеют доступ только к частным статическим участников.
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);
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;
}
Использование 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
В больших приложениях или платформах 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() {};
Это не всегда хорошая идея, но вы можете преобразовать большинство вещей с помощью кратких выражений. Важным моментом здесь является то, что не каждое значение в JavaScript является объектом, поэтому эти выражения будут успешными, если доступ к членам не-объектов, таких как null и undefined, завершится ошибкой. В частности, остерегайтесь этого typeof null == "object", но вы не можете null.toString () или ("name" в null).
Преобразование чего-либо в число:
+anything
Number(anything)
Преобразование чего-либо в беззнаковое четыре -байтное целое число:
anything >>> 0
Преобразование чего-либо в строку:
'' + anything
String(anything)
Преобразование чего-либо в логическое значение:
!!anything
Boolean(anything)
Кроме того, использование имени типа без «нового» ведет себя по-разному для String, Number и Boolean, возвращая примитивное число, строка или логическое значение, но с "новым" они будут возвращать "упакованные" типы объектов,
Хм, я не прочитал всю тему, хотя для меня это довольно интересно, но позвольте мне сделать небольшое пожертвование:
// forget the debug alerts
var alertToFirebugConsole = function() {
if ( window.console && window.console.log ) {
window.alert = console.log;
}
}
JavaScript считается очень хорошим при разоблачении всего его объекта, поэтому независимо от того, если его окно объекта.
Итак, если я хотел бы переопределить предупреждение браузера с всплывающим окном jQuery / Yui Div, который также принимает строку в качестве параметра, можно сделать, просто используя следующий фрагмент.
function divPopup(str)
{
//code to show the divPopup
}
window.alert = divPopup;
При этом изменение всех вызовов на оповещение () покажет хорошее новое всплывающее окно на основе div вместо предупреждения о конкретном браузере.
Разреженные проверки теперь в Git 1,7 .
См. также вопрос « Можно ли выполнить разреженную проверку без предварительной проверки всего хранилища? ».
Обратите внимание, что для разреженных операций извлечения требуется загрузить весь репозиторий, даже если некоторые файлы, загружаемые Git, не окажутся в рабочем дереве.
-121--1819844-Постоянно ссылайтесь на стандарты POSIX для любых используемых библиотечных функций. Части стандарта неоднозначны, и некоторые системы возвращают различные стили кодов ошибок. Это поможет вам упреждающе находить тех, кому действительно трудно найти несколько другие ошибки реализации.
-121--2434767-
Вот код переопределения функции 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);
};
};
Это скрытая особенность 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(), но пользовательские селекторы гораздо более гибкие и обычно более читаемые.