Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Вот некоторые интересные вещи:
NaN
с чем-либо (даже NaN
) всегда ложь, которая включает ==
, <
и >
.NaN
Обозначает Не Число, но если Вы просите тип, он на самом деле возвращает число.Array.sort
может взять функцию компаратора и назван подобным quicksort драйвером (зависит от реализации).$0
, $1
, $2
участники на regex.null
непохоже на что-либо еще. Это ни объект, булевская переменная, число, строка, ни undefined
. Это немного похоже на "альтернативу" undefined
. (Примечание: typeof null == "object"
)this
приводит к в других отношениях unnameable [Глобальному] объекту.var
, вместо того, чтобы просто полагаться на автоматическое объявление переменной дает времени выполнения реальный шанс оптимизации доступа к той переменнойwith
конструкция уничтожит такой optimzationsbreak
. Циклы могут маркироваться и использоваться в качестве цели continue
.undefined
. (зависит от реализации),if (new Boolean(false)) {...}
выполнится {...}
блок[обновленный немного в ответ на хорошие комментарии; см. комментарии]
Вы не должны определять параметры для функции. Можно просто использовать функцию arguments
подобный массиву объект.
function sum() {
var retval = 0;
for (var i = 0, len = arguments.length; i < len; ++i) {
retval += arguments[i];
}
return retval;
}
sum(1, 2, 3) // returns 6
Вы можете также расширяться (наследовали) классы и переопределяют свойства/методы использование цепочки прототипа , spoon16 сослался на.
В следующем примере мы создаем класс Домашнее животное и определяем некоторые свойства. Мы также переопределяем .toString () метод, наследованный от Объекта.
После этого мы создаем класс Собаки, который расширяет Домашнее животное и переопределяет .toString () метод, снова изменяющийся, это - поведение (полиморфизм). Кроме того, мы добавляем некоторые другие свойства к дочернему классу.
После этого мы проверяем, что цепочка наследования для показа той Собаки имеет все еще Собаку типа Домашнее животное типа, и текстового объекта.
// Defines a Pet class constructor
function Pet(name)
{
this.getName = function() { return name; };
this.setName = function(newName) { name = newName; };
}
// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function()
{
return 'This pets name is: ' + this.getName();
};
// end of class Pet
// Define Dog class constructor (Dog : Pet)
function Dog(name, breed)
{
// think Dog : base(name)
Pet.call(this, name);
this.getBreed = function() { return breed; };
}
// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();
// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;
// Now we override Pet.prototype.toString
Dog.prototype.toString = function()
{
return 'This dogs name is: ' + this.getName() +
', and its breed is: ' + this.getBreed();
};
// end of class Dog
var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);
// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true
Оба ответа на этот вопрос были кодами, измененными от большая статья MSDN Ray Djajadinata.
Как насчет закрытия в JavaScript (подобный анонимным методам в C# v2.0 +). Можно создать функцию, которая создает функцию или "выражение".
Пример закрытия :
//Takes a function that filters numbers and calls the function on
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
var filteredNumbers = [];
for (var index = 0; index < numbers.length; index++)
{
if (filterFunction(numbers[index]) == true)
{
filteredNumbers.push(numbers[index]);
}
}
return filteredNumbers;
}
//Creates a function (closure) that will remember the value "lowerBound"
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
return function (numberToCheck) {
return (numberToCheck > lowerBound) ? true : false;
};
}
var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];
var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);
numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);
numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);
Числа являются также объектами. Таким образом, можно сделать интересный материал как:
// convert to base 2
(5).toString(2) // returns "101"
// provide built in iteration
Number.prototype.times = function(funct){
if(typeof funct === 'function') {
for(var i = 0;i < Math.floor(this);i++) {
funct(i);
}
}
return this;
}
(5).times(function(i){
string += i+" ";
});
// string now equals "0 1 2 3 4 "
var x = 1000;
x.times(function(i){
document.body.innerHTML += '<p>paragraph #'+i+'</p>';
});
// adds 1000 parapraphs to the document
Некоторые назвали бы это вопросом вкуса, но:
aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }
trinary оператор может быть объединен в цепочку для действия как Схема (конусовидный...):
(cond (predicate (action ...))
(predicate2 (action2 ...))
(#t default ))
может быть записан как...
predicate ? action( ... ) :
predicate2 ? action2( ... ) :
default;
Это "очень функционально", поскольку это переходит Ваш код без побочных эффектов. Таким образом вместо:
if (predicate) {
foo = "one";
} else if (predicate2) {
foo = "two";
} else {
foo = "default";
}
можно записать:
foo = predicate ? "one" :
predicate2 ? "two" :
"default";
Работы, любезные с рекурсией, также:)
наследование Prototypal (популяризированный Douglas Crockford) полностью коренным образом изменяет способ, которым Вы думаете о загрузках вещей в JavaScript.
Object.beget = (function(Function){
return function(Object){
Function.prototype = Object;
return new Function;
}
})(function(){});
Это - уничтожитель! Жалость, как почти никто не использует его.
Это позволяет Вам "порождать" новые экземпляры любого объекта, расширять их, в то время как поддержание (живого) формирующего прототип наследования связывается с их другими свойствами. Пример:
var A = {
foo : 'greetings'
};
var B = Object.beget(A);
alert(B.foo); // 'greetings'
// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo); // 'hello'
A.bar = 'world';
alert(B.bar); // 'world'
// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo); // 'hello'
B.bar = 'universe';
alert(A.bar); // 'world'
Методы (или функции) можно назвать на объекте, которые не имеют типа, с которым они были разработаны для работы. Здорово назвать собственные (быстрые) методы на пользовательских объектах.
var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });
Этот код отказывает, потому что listNodes
не Array
Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);
Этот код работы, потому что listNodes
определяет достаточно подобных массиву свойств (длина, [] оператор), чтобы использоваться sort()
.
with
.
Это редко используется, и откровенно говоря, редко полезное... Но при ограниченных обстоятельствах это действительно имеет свое использование.
, Например: литералы объектов довольно удобны для того, чтобы быстро настроить свойства на новый объект. Но что, если необходимо измениться половина из свойств на существующем объекте?
var user =
{
fname: 'Rocket',
mname: 'Aloysus',
lname: 'Squirrel',
city: 'Fresno',
state: 'California'
};
// ...
with (user)
{
mname = 'J';
city = 'Frostbite Falls';
state = 'Minnesota';
}
Alan Storm указывает, что это может быть несколько опасно: если объект, используемый в качестве контекста, не делает , имеют одно из свойств, присваиваемых, это будет разрешено во внешнем объеме, возможно создавая или перезаписывая глобальную переменную. Это особенно опасно, если Вы привыкли писать код для работы с объектами, где свойства с или пустыми значениями по умолчанию оставляют неопределенными:
var user =
{
fname: "John",
// mname definition skipped - no middle name
lname: "Doe"
};
with (user)
{
mname = "Q"; // creates / modifies global variable "mname"
}
Поэтому это - вероятно, хорошая идея избежать использования with
оператор для такого присвоения.
Для надлежащего удаления свойства из объекта необходимо удалить свойство вместо того, чтобы просто установить его на неопределенный :
var obj = { prop1: 42, prop2: 43 };
obj.prop2 = undefined;
for (var key in obj) {
...
свойство prop2 все еще будет частью повторения. Если Вы хотите полностью избавиться от prop2, необходимо вместо этого сделать:
delete obj.prop2;
свойство prop2 больше не будет не делать появление, когда Вы выполните итерации через свойства.
Я должен был бы сказать самовыполнение функций.
(function() { alert("hi there");})();
, поскольку Javascript не имеет области действия блока , можно использовать самовыполняющуюся функцию, если Вы хотите определить локальные переменные:
(function() {
var myvar = 2;
alert(myvar);
})();
Здесь, myvar
, не вмешивается в или загрязняет глобальную область видимости и исчезает, когда функция завершается.
" Дополнительные методы в JavaScript" через свойство прототипа.
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] == value) return true;
}
return false;
}
Это добавит contains
метод ко всему Array
объекты. Можно назвать этот метод с помощью этого синтаксиса
var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
Также упомянутый в "JavaScript Crockford: Хорошие Части":
parseInt()
опасно. При передаче его строка, не сообщая ему о надлежащей основе, это может возвратить неожиданные числа. Например parseInt('010')
возвраты 8, не 10. Передача основы к parseInt заставляет его работать правильно:
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
Функции являются объектами и поэтому могут иметь свойства.
fn = function(x) { // ... } fn.foo = 1; fn.next = function(y) { // }
Закрытые методы
объект может иметь закрытые методы.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
// A private method only visible from within this constructor
function calcFullName() {
return firstName + " " + lastName;
}
// A public method available to everyone
this.sayHello = function () {
alert(calcFullName());
}
}
//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();
// This fails since the method is not visible from this scope
alert(person1.calcFullName());
Возможно, немного очевидный для некоторых...
Установка Firebug и использование console.log ("привет"). Настолько лучше, чем использование случайного предупреждения (); который я не забываю делать много несколько лет назад.
Если Вы Гуглите для достойной ссылки JavaScript по данной теме, включаете ключевое слово "mdc" в свой запрос, и Ваши первые результаты будут от Центра разработки Mozilla. Я не несу офлайновых ссылок или книг со мной. Я всегда использую прием ключевого слова "mdc" для прямого получения до того, что я ищу. Например:
Google: вид mdc
массива JavaScript (в большинстве случаев можно опустить "JavaScript")
Обновление: Разработчик Mozilla Центр был переименован Разработчику Mozilla Сеть . Прием ключевого слова "mdc" все еще работает, но достаточно скоро мы можем иметь к , начинают использовать "mdn" вместо этого .
можно получить доступ к свойствам объектов с []
вместо .
, Это позволяет Вам, ищут свойство, соответствующее переменной.
obj = {a:"test"};
var propname = "a";
var b = obj[propname]; // "test"
можно также использовать это для получения/устанавливания свойств объектов, имя которых не является легальным идентификатором.
obj["class"] = "test"; // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.
Некоторые люди не знают это и заканчивают тем, что использовали оценка () как это, которое является действительно плохая идея :
var propname = "a";
var a = eval("obj." + propname);
Это более трудно считать, тяжелее для нахождения ошибок в (не может использовать jslint), медленнее для выполнения, и может привести к использованию XSS.
JavaScript не имеет области действия блока (но это имеет закрытие так, давайте назовем его даже?).
var x = 1;
{
var x = 2;
}
alert(x); // outputs 2
значения по умолчанию Присвоения к переменным
можно использовать логическое или оператор ||
в выражении присваивания для обеспечения значения по умолчанию:
var a = b || c;
a
переменная получит значение c
, только если b
falsy (если будет null
, false
, undefined
, 0
, empty string
, или NaN
), то иначе a
получит значение [1 116].
Это часто полезно в функциях, когда Вы хотите дать значение по умолчанию аргументу в случае, если не предоставляется:
function example(arg1) {
arg1 || (arg1 = 'default value');
}
нейтрализация IE В качестве примера в обработчиках событий:
function onClick(e) {
e || (e = window.event);
}
<час> следующие функции языка были с нами в течение долгого времени, все реализации JavaScript поддерживают их, но они не были частью спецификации до 5-й Выпуск ECMAScript:
debugger
оператор
, Описанный в: § 12.15 Оператор
отладчика Этот оператор позволяет Вам помещать точки останова программно в Вашем коде только:
// ...
debugger;
// ...
, Если отладчик присутствует или активен, он заставит его сразу повредиться, исправиться на той строке.
Иначе, если отладчик не присутствует или активен, этот оператор не имеет никакого заметного эффекта.
Многострочные Строковые литералы
Описанный в: § 7.8.4 Строковые литералы
var str = "This is a \
really, really \
long line!";
необходимо быть осторожными, потому что символ рядом с \
должен быть разделителем строки, если у Вас есть пространство после того, как \
, например, код будет взгляд точно то же, но это повысит SyntaxError
.
Можно использовать в оператор, чтобы проверить, существует ли ключ в объекте:
var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true
при нахождении литералов объектов слишком ужасными можно объединить его с функциональной подсказкой без параметров:
function list()
{ var x = {};
for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
return x
}
5 in list(1,2,3,4,5) //true
Функции являются гражданами первого класса в JavaScript:
var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
var sum = function(x,y,z) {
return x+y+z;
};
alert( passFunAndApply(sum,3,4,5) ); // 12
методы Функционального программирования могут использоваться для записи изящного javascript.
Особенно, функции могут быть переданы как параметры, например, , Array.filter () принимает обратный вызов:
[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]
можно также объявить "частную" функцию, которая только существует в рамках определенной функции:
function PrintName() {
var privateFunction = function() { return "Steve"; };
return privateFunction();
}
Можно поймать исключения в зависимости от их типа. Заключенный в кавычки от MDC:
try {
myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
// statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
// statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
// statements to handle EvalError exceptions
} catch (e) {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
ПРИМЕЧАНИЕ: Условными пунктами выгоды является Netscape (и следовательно Mozilla/Firefox) расширение, которое не является частью спецификации ECMAScript и следовательно не может быть положено за исключением конкретных браузеров.
Можно использовать объекты вместо переключателей большую часть времени.
function getInnerText(o){
return o === null? null : {
string: o,
array: o.map(getInnerText).join(""),
object:getInnerText(o["childNodes"])
}[typeis(o)];
}
Обновление: если Вы обеспокоены случаями, оценивающими заранее быть неэффективным (почему Вы волнуетесь по поводу эффективности это вначале в дизайне программы??) затем можно сделать что-то вроде этого:
function getInnerText(o){
return o === null? null : {
string: function() { return o;},
array: function() { return o.map(getInnerText).join(""); },
object: function () { return getInnerText(o["childNodes"]; ) }
}[typeis(o)]();
}
Это более обременительно, чтобы ввести (или читать) или, чем переключатель или, чем объект, но он сохраняет преимущества использования объекта вместо переключателя, детализированного в разделе комментариев ниже. Этот стиль также делает это более простым для затягивания этого в надлежащий "класс", после того как это растет достаточно.
update2: с предложенными расширениями синтаксиса для ES.next это становится
let getInnerText = o -> ({
string: o -> o,
array: o -> o.map(getInnerText).join(""),
object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);
Частные переменные с Открытым интерфейсом
Это использует аккуратный небольшой прием с определением функции самовызова. Все в объекте, который возвращается, доступно в открытом интерфейсе, в то время как все остальное является частным.
var test = function () {
//private members
var x = 1;
var y = function () {
return x * 2;
};
//public interface
return {
setx : function (newx) {
x = newx;
},
gety : function () {
return y();
}
}
}();
assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());
Обязательно используйте метод hasOwnProperty при итерации через свойства объекта:
for (p in anObject) {
if (anObject.hasOwnProperty(p)) {
//Do stuff with p here
}
}
Это сделано так, чтобы Вы только получили доступ прямые свойства anObject и не использовали свойства, которые снижаются на цепочку прототипа.
Первое, что пришло на ум...
Функции
arguments.callee относится к функции, которая размещает переменную "аргументов", таким образом, это может использоваться для рекурсивного вызова анонимных функций:
var recurse = function() {
if (condition) arguments.callee(); //calls recurse() again
}
Это полезно, если Вы хотите сделать что-то вроде этого:
//do something to all array items within an array recursively
myArray.forEach(function(item) {
if (item instanceof Array) item.forEach(arguments.callee)
else {/*...*/}
})
Объекты
интересная вещь об элементах объекта: у них может быть любая строка как их имена:
//these are normal object members
var obj = {
a : function() {},
b : function() {}
}
//but we can do this too
var rules = {
".layout .widget" : function(element) {},
"a[href]" : function(element) {}
}
/*
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
var elements = document.querySelectorAll(rules[item]);
for (var e, i = 0; e = elements[i++];) rules[item](e);
}
Строки
String.split может взять регулярные выражения в качестве параметров:
"hello world with spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]
String.replace может взять регулярное выражение в качестве поискового параметра и функции как заменяющий параметр:
var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"
Я мог заключить большей части превосходной книги Douglas Crockford в кавычки JavaScript: Хорошие Части .
, Но я возьму всего один для Вас, всегда использовать ===
и !==
вместо ==
, и !=
alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true
==
не является переходным. Если бы Вы используете ===
, это дало бы ложь для всех этих операторов как ожидалось.
Узнайте, сколько параметров ожидается функцией
function add_nums(num1, num2, num3 ){
return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.
. Узнайте, сколько параметров получает функция
function add_many_nums(){
return arguments.length;
}
add_many_nums(2,1,122,12,21,89); //returns 6
Я знаю, что опоздал на вечеринку, но я просто не могу поверить, что полезность оператора +
не была упомянута помимо "преобразования чего-либо в число". Может быть, это настолько скрытая функция?
// Quick hex to dec conversion:
+"0xFF"; // -> 255
// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();
// Safer parsing than parseFloat()/parseInt()
parseInt("1,000"); // -> 1, not 1000
+"1,000"; // -> NaN, much better for testing user input
parseInt("010"); // -> 8, because of the octal literal prefix
+"010"; // -> 10, `Number()` doesn't parse octal literals
// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null; // -> 0;
// Boolean to integer
+true; // -> 1;
+false; // -> 0;
// Other useful tidbits:
+"1e10"; // -> 10000000000
+"1e-4"; // -> 0.0001
+"-12"; // -> -12
Конечно, вы можете сделать все это, используя Number()
, но оператор +
намного красивее!
Вы также можете определить числовое возвращаемое значение для объекта, переопределив метод прототипа valueOf()
. Любое преобразование чисел, выполненное для этого объекта, приведет не к NaN
, а к возвращаемому значению метода valueOf()
:
var rnd = {
"valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd; // -> 442;
+rnd; // -> 727;
+rnd; // -> 718;