Комментарии 150
Для получения того самого типа — внутреннего свойства
Еще есть интересная особенность оператора new — он не может вызвать функцию у которой нет свойства prototype — все нативные функции и функции
[[Class]]
можно использовать особенность работы Object.prototype.toString
и написать вот такой кодvar allowedTypes = ["Object", "Undefined", "Null", "Boolean", "Number", "String"];
/**
* @param {Mixed} x
*
* @return {String}
*/
function Type(x) {
var type = Object.prototype.toString.call(x).replace(/^\[object\s|\]$/g, '');
return ~allowedTypes.indexOf(type) && type || "Object";
}
Еще есть интересная особенность оператора new — он не может вызвать функцию у которой нет свойства prototype — все нативные функции и функции
() =>
из ES6new Array.prototype.slice
// TypeError: Array.prototype.slice is not a constructor
// VS
var A = function () {};
Object.getOwnPropertyDescriptor(A, "prototype");
// {"configurable":false,"enumerable":false,"value":{},"writable":true}
// Убить prototype у пользовательской функции нельзя
delete A.prototype; // false - "configurable":false
new A(); // ok
+11
Спасибо за пример, таким способом действительно можно получить тип объекта, но, как я и говорил вышел, не вижу этому применения
0
Это и многое другое можно найти в JS Garden:
shamansir.github.com/JavaScript-Garden/#types.typeof
shamansir.github.com/JavaScript-Garden/#types.typeof
+3
с typeof и [[Class]] вообще интересного много: blgo.ru/t/jstypes/table/
0
По второму уточню: не в отсутствии prototype дело, а в отсутствии внутреннего метода [[Construct]]:
Array.prototype.slice.prototype={}
new Array.prototype.slice // TypeError: function slice() { [native code] } is not a constructor
+2
Какая хорошая статья, спасибо!
-2
И правда, в этом месяце на Хабре ещё не было описания подводных камней JS.
+20
> в любой момент мы можем прочитать и записать значение undefined, следовательно, кто-то может перезаписать его за нас и сравнение с undefined будет некорректным.
С таким же успехом кто-то может перезаписать все свойства документа, jQuery, и методы массивов. После этого он может облить ваш компьютер бензином и поджечь его.
С таким же успехом кто-то может перезаписать все свойства документа, jQuery, и методы массивов. После этого он может облить ваш компьютер бензином и поджечь его.
+16
Нелогично то, что кто-то может это сделать с undefined, но не может, например, с NaN. undefined так же могло быть not-writable свойством — это было бы логично.
А jQuery пока не является нативным объектом JS, так что не будем о нём в этой статье ;)
А jQuery пока не является нативным объектом JS, так что не будем о нём в этой статье ;)
0
НЛО прилетело и опубликовало эту надпись здесь
Вот Вы иронизируете, а у меня когда-то получилось сделать это непреднамеренно.
0
хорошо бы узнать как автор сделает это в глобальном контексте. в локальном это возможно — но это тогда будет Ваша проблема, а не глобальная.
0
В js чем меньше знаешь, тем лучше спишь:
только что сделал
только что сделал
var x = 1000/0;
console.log(typeof x); // number
console.log(typeof 1000/0) // NaN
-1
var x = 1000/0;// — это бесконечность, Infinity, тип Number.
console.log(typeof x); // number, всё верно
console.log(typeof 1000/0) // NaN
//Теперь поставим скобки правильно:
console.log((typeof 1000)/0); //NaN
console.log(typeof(1000/0)); //Number
Всё логично:)
console.log(typeof x); // number, всё верно
console.log(typeof 1000/0) // NaN
//Теперь поставим скобки правильно:
console.log((typeof 1000)/0); //NaN
console.log(typeof(1000/0)); //Number
Всё логично:)
+20
О спасибо. Как-то казалось оператор деления будет иметь приоритет перед typeof. Тогда да логично.
0
А когда 1000/0 стал безконечностью?
1000/0 как раз таки неопределенность, поскольку не существует числа, которое при умножении на 0 даст 1000. И бесконечность при умножении на 0 не даст 1000.
1000/0 как раз таки неопределенность, поскольку не существует числа, которое при умножении на 0 даст 1000. И бесконечность при умножении на 0 не даст 1000.
+2
НЛО прилетело и опубликовало эту надпись здесь
В комментарии KELiON «это бесконечность, Infinity, тип Number.»
Кроме того, даже если бесконечность не число — с чего вдруг бесконечность умножить на 0 будет 1000?
Кроме того, даже если бесконечность не число — с чего вдруг бесконечность умножить на 0 будет 1000?
0
НЛО прилетело и опубликовало эту надпись здесь
Потому что математическая операция деления — обратима. И она не должна возвращать Infinity.
0
НЛО прилетело и опубликовало эту надпись здесь
Я ведь делю 1000 на 0. Это числа?
0
НЛО прилетело и опубликовало эту надпись здесь
Продолжайте строить из себя умника, не уважающего других. Вы уже ОЧЕНЬ близко к цели.
0
1000/0 — это бесконечность, если исходить из математики. Т.к. если делить 1000 на бесконечно малое число, то получим бесконечность. Грубо говоря 0 это вообще ничего не существует, всегда хоть что то да есть, даже что то бесконечно малое. Вот и выходит, что 1000 / (1/10000000000000) получается бесконечно большое число.
P.S. во я завернул)
P.S. во я завернул)
-1
Да не правда это. Ноль — это строго ноль. 1/10000000000000 — не ноль, хоть тысячу раз в квадрат возведите. Нужно понимать, что есть разница между нулем, и бесконечно малым.
0
Вы немного путаете. Бесконечности будет равен предел выражения 1000/x, где x приближается к нулю. В математике результат деления на 0 же неопределен.
+1
По хорошему, при выходе за границы применимости следовало бы бросать исключение.
0
Она-то обратима, вот только делить на ноль нельзя. Разработчики ECMAScript (и не одни они) это решили весьма интересным (и часто очень удобным) способом.
-2
На 0 делить нельзя только в элементарной алгебре. Я с первого курса матнализа помню, что:
В решении JS нет ничего интересного, если заменить неопределенность на NaN, а бесконечность на Infinity. Операции с ними не противоречат матанализу. Единственное замечание — в JS нет разницы между +0 и -0, но есть Infinity и -Infinity.
- 0/0 — неопределенность,
- любое положительное число делить на 0 = +∞
- любое отрицательное число число делить на 0 = -∞
- ∞/∞ — неопределенность
- ∞*∞=∞
В решении JS нет ничего интересного, если заменить неопределенность на NaN, а бесконечность на Infinity. Операции с ними не противоречат матанализу. Единственное замечание — в JS нет разницы между +0 и -0, но есть Infinity и -Infinity.
+4
любое положительное число делить на положительное число СТРЕМЯЩЕЕСЯ К НУЛЮ равно числу, СТРЕМЯЩЕМУСЯ К БЕСКОНЕЧНОСТИ.
+1
Не вижу противоречия: 0 стремится к 0, а ∞ стремится к ∞
0
Мы говорим о разных вещах. НА НОЛЬ ДЕЛИТЬ НЕЛЬЗЯ, никак.
На курсе матана вы проходили ПЕРЕМЕННЫЕ стремящиеся к нулю/бесконечности.
5 / 0 — бред, это только для упрощения пишут, например, 0/0. На деле подразумевается x/y при x, y -> 0.
— Единственное замечание — в JS нет разницы между +0 и -0
Глупости:
console.log( 1/(-0) )
На курсе матана вы проходили ПЕРЕМЕННЫЕ стремящиеся к нулю/бесконечности.
5 / 0 — бред, это только для упрощения пишут, например, 0/0. На деле подразумевается x/y при x, y -> 0.
— Единственное замечание — в JS нет разницы между +0 и -0
Глупости:
console.log( 1/(-0) )
+1
В ECMAScript в The Abstract Equality Comparison Algorithm отдельным пунктом прописывается
Деление же на 0 со знаком Applying the / Operator опирается на IEEE 754
PS Я прекрасно понимаю ваши чувства и то, что для получения бесконечности надо поделить на бесконечно малую величину, а не ноль. Вы так же «поймите и простите» ECMAScript :)
-0 == +0
Деление же на 0 со знаком Applying the / Operator опирается на IEEE 754
Division of a non-zero finite value by a zero results in a signed infinity. The sign is determined by the rule already stated above.
PS Я прекрасно понимаю ваши чувства и то, что для получения бесконечности надо поделить на бесконечно малую величину, а не ноль. Вы так же «поймите и простите» ECMAScript :)
0
5/0 — это не бред. это элемент кольца замыкание®, а именно бесконечность.
0
Можно подробнее? Хотя бы, куда копать?
-1
вообще 5/0 = 5*(0)^(-1) = 5*Infinity = Infinity (при этом обратного к Infiniti не существует)
/ — это ведь просто значёк для упрощения записи умножения на обратный эллемент
А ещё это алгебра и теория чисел, а не матан
/ — это ведь просто значёк для упрощения записи умножения на обратный эллемент
А ещё это алгебра и теория чисел, а не матан
0
Просто меня смущает то, что вы выше написали… Разве можно говорить, что бесконечность есть обратный элемент относительно операции умножения для нуля? Вроде в определении поля как раз у него нет обратного.
Или я путаю понятия?
Или я путаю понятия?
0
Если вы смотрите на это как на поле, то вы правы, но можно смотреть как на кольцо. Тогда можно к R добавить два элемента +-бесконечность и доопределить нужные операции. При этом довольно формально можно определить операцию деления и обратные для некоторых элементов (кольцо не требует их существования).
А в поле R всё верно R* = R\{0} — множество обратимых элементов.
А в поле R всё верно R* = R\{0} — множество обратимых элементов.
0
Давайте решим, что на ноль делить нельзя, т.к. это абсурдно с логической точки зрения? :) Чтобы не думать о вариантах математических объектов.
-2
А давайте решим, что деление на ноль даёт бесконечность, чтобы не продолжать этот бессмысленный спор.
0
можно согласиться, что 5/0 — это формальность. делить — это тоже формальность =)
можно только умножать и брать обратный. вы можете работать с кольцом R U {+-Infinity, NaN} и определить все правила умножения — это просто. А потом формально доопределить обратные элементы для того, чтобы «делить». В общем-то так и делают все ЯП.
И ничего тут абсурдного нет, так ведь можно сказать что комплексные числа тоже абсурд с логической точки зрения =)
можно только умножать и брать обратный. вы можете работать с кольцом R U {+-Infinity, NaN} и определить все правила умножения — это просто. А потом формально доопределить обратные элементы для того, чтобы «делить». В общем-то так и делают все ЯП.
И ничего тут абсурдного нет, так ведь можно сказать что комплексные числа тоже абсурд с логической точки зрения =)
+1
0 не стремится к 0, 0 достиг нуля.
0
1000/0 - Infinity, 0/0 - NaN, NaN !== NaN
Это все IEEE 754 +1
Ну наконец-то. Читал эту ветку и ужасался :) Действительно, достаточно просто сказать, что реализация Number соответствует стандарту IEEE 754 для чисел удвоенной точности. Откуда следует, в частности, что:
и прочие «забавные» вещи.
console.log((1e+16 + 1) == 1e+16); //true
console.log((1e+16 + 100) == 1e+16); //false
и прочие «забавные» вещи.
+1
НЛО прилетело и опубликовало эту надпись здесь
нет — это проблема при оптимизации арифметеки. Я с такой проблемой столкнулся в mongoDB — там тоже пришлось делать враппер над представлениями чисел.
+1
Почему нет? Это типичная ошибка огругления float. Вот почему к нему кастуется — другой вопрос.
0
demotivation.me/images/20081101/vunait9sj64n.jpg :)
(не к Вам лично, а по поводу темы треда)
(не к Вам лично, а по поводу темы треда)
0
Потому что стандарт: www.ecma-international.org/ecma-262/5.1/#sec-4.3.19
В javascript Number — это double
В javascript Number — это double
+2
Для получения реального «undefined»-значения можно использовать оператор void (кстати, я не знаю другого применения этому оператору):
Помимо
void 0 == undefined
void можно использовать для красивого замыкания без лишних скобок:
void function(global) {
//closure
} (this);
+2
А еще из-за особенностей внутреннего представления JavaScript объектов V8 и Оперы в хэше сперва идут числа в порядке убывания, а потом стоковые элементы в порядке добавления. Притом, что при использовании ключа большего, чем 1e+9 ключи в них воспринимаются как строки и идут в порядке добавления.
Мораль: не мешайте стоковые ключи с числовыми. Не опирайтесь на порядок добавления элементов в «Хэш».
var a = {};
a['pewpew'] = 1;
a['ololo'] = 2;
a[1] = 3;
a[0] = 4;
a[1e+9] = 5;
a[1e+10] = 6;
JSON.stringify(a);
JSON.stringify(a);
// V8 (Chrome, Node,js) и Опера
// {"0":4,"1":3,"1000000000":5,"pewpew":1,"ololo":2,"10000000000":6}
// FireFox и Safari
// {"pewpew":1,"ololo":2,"1":3,"0":4,"1000000000":5,"10000000000":6}
Мораль: не мешайте стоковые ключи с числовыми. Не опирайтесь на порядок добавления элементов в «Хэш».
+3
Не знал о таких тонкостях, но почти во всех языках, включая js, хеши (в данном случае объекты) не гарантируют определенного порядка прохода по ключам, работая с ключами, как с неупорядоченным множеством.
+1
В настоящее время во всех браузерах (и в Node.js также) ключи хэша выводятся в том порядке, в котором они были вставлены в объект, за исключением поведения Хрома и Оперы с числовыми ключами. Поэтому для получения ключей в порядке их поступления достаточно следовать двум простым правилам:
(Правила взятыиз README-файла от библиотеки jParser.)
- Имя ключа не должно начинаться с цифры (или со знака «+»
или «−» с последующею цифрою).
- Один и тот же ключ не должен добавляться в один и тот же объект дважды.
(Правила взяты
+1
Сижу и тихо млею. Неужели кто-то до сих пор использует числа с плавающей точкой для работы с деньгами?
Единственно правильная реализация денежных операций — работать с самой маленькой денежной единицей, можно даже в абстрактной. Для отображения используются таблицы трансформаций в более крупную валюту.
В странах Европы принято деление 1:100, т.е. рубль состоит из 100 копеек, гривна = 100копеек, евро = 100 центов. Значит операции производятся в копейках, рубль получается путем деления на 100 нужной суммы.
В Англии до 1971 использовалась более сложная схема 1 фунт = 20 шиллингам, шиллинг = 12 пенсов. Соответственно должна составляться таблица последовательных преобразований из пенсов в фунты, так как цена могла быть отображена в виде 1 фунт, 2 шиллинга, 4 пенса.
Некоторые страны имеют соотношение 1 к 1000, например ливийский динар состоит из 1000 дирхамов, а на Мадагаскаре и в Мавритании соотношение 1 к 5. В Японии нет деления на более мелкие валюты, там все операции производятся в иенах.
Вы все еще используете вещественные числа для рассчета валют? Тогда рефакторинг ждет вас! :)
Единственно правильная реализация денежных операций — работать с самой маленькой денежной единицей, можно даже в абстрактной. Для отображения используются таблицы трансформаций в более крупную валюту.
В странах Европы принято деление 1:100, т.е. рубль состоит из 100 копеек, гривна = 100копеек, евро = 100 центов. Значит операции производятся в копейках, рубль получается путем деления на 100 нужной суммы.
В Англии до 1971 использовалась более сложная схема 1 фунт = 20 шиллингам, шиллинг = 12 пенсов. Соответственно должна составляться таблица последовательных преобразований из пенсов в фунты, так как цена могла быть отображена в виде 1 фунт, 2 шиллинга, 4 пенса.
Некоторые страны имеют соотношение 1 к 1000, например ливийский динар состоит из 1000 дирхамов, а на Мадагаскаре и в Мавритании соотношение 1 к 5. В Японии нет деления на более мелкие валюты, там все операции производятся в иенах.
Вы все еще используете вещественные числа для рассчета валют? Тогда рефакторинг ждет вас! :)
+9
ну давайте положим 1 рубль на счет и начнем ежедневно добавлять сотые доли процента %)
+4
Поэтому в банках добавляют еще две цифры запаса (то есть считают всё в сотых долях копеек), а выводят с округлением до целых копеек.
0
в банках используют особый денежный формат 21:5 — т.е. 21 цифра для целых частей, и 5 для дробных, как правило более 4 знаков после запятой при делении валюты или начисления % не используется, а последний 5 разряд после запятой используйте как корректирующий для случаев проблем округления, также дополнительно используется расширенные правила округления (чаще по IEEE, но иногда и по локальным стандартам — для РФ — стандарт ЦБ РФ и МинФин РФ)
+6
Во!
А то ходють тут любители рефакторинга и махают своим единственно правильным!
А то ходють тут любители рефакторинга и махают своим единственно правильным!
0
Есть один нюанс, для всех операций используется decimal floating point арифметика, в которой число хранится в целочисленке.
0
ну вот есть у меня на счете 99 рублей и 99.98 копеек, выводить будет 100 рубликов, а снять их не даст, ибо с нужной точностью их нету
0
вообще-то нет — обычно запрещено округлять подобным образом. в случае «грязного» округления дробная часть отбрасывается вовсе и Вам тогда отобразят 99, ОДНАКО «грязное» округление уже нигде не используется, если только за исключением каких либо аггрегированных показателей в регистрах накопителях для целей внутреннего учета.
0
Приходится :)
Например, пользователь хочет перевести 36.3 USD на счет. Конечно, мы переводим эту сумму в центы, но в итоге получится float :)
36.3 * 100 = 3629.9999999999995
Например, пользователь хочет перевести 36.3 USD на счет. Конечно, мы переводим эту сумму в центы, но в итоге получится float :)
36.3 * 100 = 3629.9999999999995
0
Еще, на всякий случай напомню одну особенность которую данный программист не учел:
Хотя умножение/деление на 10 решает проблему
>>> (0.7*10 + 0.1*10)/10
0.8
но вот незадача
>>> (0.07*10 + 0.02*10)/10
0.09000000000000001
Не нужно всегда думать что у вас числа будут только с десятками, даже одна копейка при таких арифметических действиях может выйти в серьезную проблему.
Хотя умножение/деление на 10 решает проблему
>>> (0.7*10 + 0.1*10)/10
0.8
но вот незадача
>>> (0.07*10 + 0.02*10)/10
0.09000000000000001
Не нужно всегда думать что у вас числа будут только с десятками, даже одна копейка при таких арифметических действиях может выйти в серьезную проблему.
0
Это проблема не яваскрипта, а особенность работы компьютера с float. floating-point-gui.de/
-1
Чем-то напомнило старый добрый боян "...enough making fun of programming languages, let's talk about Javascript."
0
Дополню:
- При арифметических
null
приводится к нулю.null+1===1
Это не то поведение, которого ждёшь отnull
после СУБД. Зачем нужен такойnull
, непонятно — вместо него кажется правильным использоватьundefined
. - Начиная с JavaScript 1.8.5 (Firefox 4),
undefined
неперезаписываемое, согласно спецификации ECMAScript 5.
0
Кто может объяснить это? Один раз увидел, и с тех пор меня мучают ночные кошмары.
[] + [] = ""
[] + {} = "[object Object]"
{} + [] = 0
{} + {} = NaN
+1
//(1) [] + [] = ""
[].toString() // -> "" - Array не является нативным типом - поэтому сериализуется черезе .toString()
"" + "" // -> "" - сложение двух пустых строк равняется пустой строке
//(2) [] + {} = "[object Object]"
{}.toString() // -> "[object Object]" - {} является упрощенной формой new Object()
[].toString() // -> "" - Array не является нативным типом - поэтому сериализуется через .toString()
"" + {} // -> "[object Object]" - сложение строки с объектом невозможно, результат Object
//(3) {} + [] = 0 и {} + {} = NaN
// тут есть одна особенность - результат зависит от движка
// Mozilla Rhino, Opera Presto/2.12.388, Microsoft Trident
{} + [] = 0.0 // действует правило конвертации пустых объектов (нативный тип + ненативный тип), массивы конвертируются в "", объект в 0.
// тоже самое будет если
0 /*{}*/ + "" /*[]*/ = 0.0
{} + {} = NaN // попытка приведения объекта к типу "number" приводит к NaN - что по сумме дает NaN т.к. оба аргумента неприводимы в тип доступный для складывания
// Google V8
{} + [] = "[object Object]"
{} + {} = "[object Object][object Object]"
+6
НЛО прилетело и опубликовало эту надпись здесь
Посмотрите внимательно — ЗАВИСИТ от движка, разные движки по разному собирают внутреннее представление.
Я поэтому и описал 2 вариант — (1) V8 (2) Все остальные движке (Rhino, Presto, Trident)
Я поэтому и описал 2 вариант — (1) V8 (2) Все остальные движке (Rhino, Presto, Trident)
0
НЛО прилетело и опубликовало эту надпись здесь
вообще-то Вы своим комментов наоборот это подтвердили :)
значение пустой строки как раз "" а не 0
значение пустой строки как раз "" а не 0
// Rhino
{} + 1 = 1.0 // {} = 0.0
[] + 1 = 1 // [] = 0
0
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
в этой-же статье не учтено что движок V8 по другому парсит и обрабатывает код — конкретный пример Я привел выше.
P.S. а т.к. V8 относится и к Chrome и node.js — то автоматически к этому применимо. А вот у Safari используется модифицированный WebKit с другим движком.
P.S. а т.к. V8 относится и к Chrome и node.js — то автоматически к этому применимо. А вот у Safari используется модифицированный WebKit с другим движком.
0
{}+{}
В этом примере нет операции сложения. Это пустой блок и «плюс пустой объект» (как +2). Приведение пустого объекта к числу дает NaN.
В этом примере нет операции сложения. Это пустой блок и «плюс пустой объект» (как +2). Приведение пустого объекта к числу дает NaN.
+1
Углубльсю немного в один из примеров.
Завист все от того места, куда этот экспрешн будет вставлен:
Дело в том, что парсер воспринимает в 1-м примере скобки как пустой блок
вот так:
То как воспринял данный код браузер можно понять, используя вот такой хак
А вот в этом случае оба блоки
Если поставить наше самое первое выражение в стейтмент (реальное условие), то парсер будет думать, что фигурные скобки это литерал объекта из-за того, что стейтмет var еще не закрыт.
Проще говоря, эти случаи предельно синтетические и в реальности их словить нельзя.
Завист все от того места, куда этот экспрешн будет вставлен:
{} + ""; // 0
"" + {}; // "[object Object]"
Дело в том, что парсер воспринимает в 1-м примере скобки как пустой блок
вот так:
{;}
+""; // 0
Во втором случае скобки — литерал объекта т.к. стейтмент плюс еще не закрыт.То как воспринял данный код браузер можно понять, используя вот такой хак
Function.prototype.toString();
(function(){{}+""})+"";
/*FF распарсил эту функцию вот так:
"function () {
+ "";
}"*/
/*Опера
"function() {
{}
+""
}"
*/
/*Хром
"function (){{}+""}"
*/
/*Сафари
"function () {{}+"";}
*/
А вот в этом случае оба блоки
{2+1;} + ""; // 0 - аналогично первому примеру
"" + {2+1;}; // Syntax error - пытается распарсить блок {2+1;} как литерал объекта
Если поставить наше самое первое выражение в стейтмент (реальное условие), то парсер будет думать, что фигурные скобки это литерал объекта из-за того, что стейтмет var еще не закрыт.
var a = {} + ""; // "[object Object]"
Проще говоря, эти случаи предельно синтетические и в реальности их словить нельзя.
+2
Пара дополнений.
1.
Так как в JS, всё — объекты, лучше использовать более универсальный и логичный оператор instanceof. Им можно сверять типы любых объектов, например:
Для проверки на нулевые значения, лучше использовать прямые сравнения, вроде
2.
Значение Infinity также имеет свои особенности:
Существует как +Infinity, так и -Infinity.
3.
Если запрашивать не объявленную переменную, то будет ошибка.
Но если запрашивать туже переменную, через свойство объекта, то ошибки не будет.
В JS, всё — свойство какого либо объекта.
1.
оператор typeof используется довольно часто, поэтому лучше запомнить
Так как в JS, всё — объекты, лучше использовать более универсальный и логичный оператор instanceof. Им можно сверять типы любых объектов, например:
[] instanceof Array // true
Для проверки на нулевые значения, лучше использовать прямые сравнения, вроде
var === undefined
2.
Значение Infinity также имеет свои особенности:
Infinity + 1 == Infinity // true
Существует как +Infinity, так и -Infinity.
3.
Если запрашивать не объявленную переменную, то будет ошибка.
someVar; // error
Но если запрашивать туже переменную, через свойство объекта, то ошибки не будет.
window.someVar; // undefined
В JS, всё — свойство какого либо объекта.
0
Из-за особенностей работы оператора instanceof такая операция не пройдет, если вы будете проверять инстанс у массива во фрейме.
В этом случае используют особенность алгоритма
Это требование зависит как от кодстайла так и от алгоритма. Однозначано так говорить не хорошо.
frame.contentWindow.var instanceof Array;
В этом случае используют особенность алгоритма
Object.prototype.toString
и получают «Тип» из [[Class]]
var === undefined
Это требование зависит как от кодстайла так и от алгоритма. Однозначано так говорить не хорошо.
В JS, всё — свойство какого либо объекта.Вы про какие объекты сейчас говорите? Даю код исключительно для уточнения ваших слов.
function a() {
var a; // свойство какого объекта переменная а?
}
Если запрашивать / Но если запрашиватьтут важно понимание операций Identifier Resolution и Property Accessors, а не их последствий :)
0
Вообще с введением Harmony разницы особой не будет, можно будет поставить прокси на GLOBAL область и ловить исключения несуществующей переменной в рантайме.
В JS действительно — ВСЕ свойства какого либо объекта, просто не ко всем контекстам есть доступ — например к локальным переменным + без сохранения контекста видимости код с функцией a действительно будет «волшебными грибами».
От себя добавлю — сделал библиотеку typeis(«typename»)(object) — это позволяет ВСЕГДА гарантированно проверять тип объекта без лишних проблем, в т.ч. и проблема несуществующих переменных решает :)
В JS действительно — ВСЕ свойства какого либо объекта, просто не ко всем контекстам есть доступ — например к локальным переменным + без сохранения контекста видимости код с функцией a действительно будет «волшебными грибами».
От себя добавлю — сделал библиотеку typeis(«typename»)(object) — это позволяет ВСЕГДА гарантированно проверять тип объекта без лишних проблем, в т.ч. и проблема несуществующих переменных решает :)
0
ловить исключения несуществующей переменной в рантаймеОшибку лучше предотвратить, чем обработать исключение.
можно будет поставить прокси на GLOBAL областьВы уверены в понимании идеи Proxy? :) Пример, пожалуйста (Proxy сейчас есть в Firefox).
В JS действительно ВСЕ свойства какого либо объектаЭто я прекрасно понимаю. Хотел уточнить знание автора комента выше, а тут вы :)
сделал библиотеку typeis(«typename»)(object)Из многолетнего опыта — мне всегда хватало typeof и Array.isArray. Зря вы так GC мучаете своими «красивыми» функциональными интерфейсами :)
typeis("typename")(object);
type(object) === "typename"; // faster - true, better IMO
0
1) ОК, если Вы такой маг и все пишите сразу отлично — то спорить не буду, мне лично проще вести трассировку подобным образом
2) идея Proxy это расширенный полиморфизм и метапрограммирование
3) сорри, не распознал сарказма
4) GC не не жалко, можно и вручную собрать — в моем вариант просто функционал шире, т.к. он позволяет верифицировать ОЧЕНЬ много custom типов — например Country (проверка страны по ISO), время, составные типы по паттернам и т.д. — также это позволяет ввести НЕнативный тип и использовать его 1 строкой с расширенной валидацией, теоретически можно и перегрузить typeof/type — но как мне кажется лучше не стоит. (например перегрузки и расширения свойств Object плохо совместимы с ранними версиями express.js)
P.S. Я например проверяю размеры typeis("<10KB")(number) или например так typeis("<MAX_FILE_SIZE")(number) — так весьма удобно ИМХО.
2) идея Proxy это расширенный полиморфизм и метапрограммирование
3) сорри, не распознал сарказма
4) GC не не жалко, можно и вручную собрать — в моем вариант просто функционал шире, т.к. он позволяет верифицировать ОЧЕНЬ много custom типов — например Country (проверка страны по ISO), время, составные типы по паттернам и т.д. — также это позволяет ввести НЕнативный тип и использовать его 1 строкой с расширенной валидацией, теоретически можно и перегрузить typeof/type — но как мне кажется лучше не стоит. (например перегрузки и расширения свойств Object плохо совместимы с ранними версиями express.js)
P.S. Я например проверяю размеры typeis("<10KB")(number) или например так typeis("<MAX_FILE_SIZE")(number) — так весьма удобно ИМХО.
0
Вообще то подумал про window, если говорить про «всё — свойство какого либо объекта». Хотя window и является сам свойством window, но не считаю что такой трюк равняет window с другими объектами.
По сути, должен быть один корневой элемент, и от этого не уйти. Даже строя кольцо из указателей, нужно помнить что начинается его строительство с одного элемента. Первый же созданный указатель на этот элемент из вне JS среды и является переменной не являющейся свойством какого либо объекта.
По сути, должен быть один корневой элемент, и от этого не уйти. Даже строя кольцо из указателей, нужно помнить что начинается его строительство с одного элемента. Первый же созданный указатель на этот элемент из вне JS среды и является переменной не являющейся свойством какого либо объекта.
0
Код о Harmony Proxy и Identifier Resolution.
var windowDescriptor = Object.getOwnPropertyDescriptor(this, 'window');
// {"configurable":false,"enumerable":true,"value":window,"writable":false}
this.window = Proxy.create({}); // (А) "writable":false - ничего не получится
window.__noSuchMethod__ = function () {
return function () {};
}
window.b(); // OK __noSuchMethod__ тут сработает
b(); // (B) ReferenceError: b is not defined
0
Я работаю с node.js и тут можно использовать циклическую переменную GLOBAL — например переопределив ее так
(function(){ GLOBAL = Proxy.create({}); })();
0
Попробовать, к сожалению не могу.
Но даже если мы перепишем GLOBAL на проксю, то от Identifier Resolution это не поможет.
Вобщем проксю не подмешать без патчинга ноды.
» node -v
v0.8.8
» node --harmony_proxies
> GLOBAL = Proxy.create({get: console.log.bind(console)});
util.js:120
var ctx = {
^
RangeError: Maximum call stack size exceeded
Но даже если мы перепишем GLOBAL на проксю, то от Identifier Resolution это не поможет.
» node
> GLOBAL = {a: 1};
{ a: 1 }
> a;
ReferenceError: a is not defined
at repl:1:1
at REPLServer.self.eval (repl.js:111:21)
at rli.on.e (repl.js:260:20)
at REPLServer.self.eval (repl.js:118:5)
at Interface.<anonymous> (repl.js:250:12)
at Interface.EventEmitter.emit (events.js:88:17)
at Interface._onLine (readline.js:199:10)
at Interface._line (readline.js:517:8)
at Interface._ttyWrite (readline.js:735:14)
at ReadStream.onkeypress (readline.js:98:10)
>
Вобщем проксю не подмешать без патчинга ноды.
0
1) ЕСТЕСТВЕННО
Для корректной перегрузки GLOBAL Вам нужно сделать 3 действия:
1) скопировать оригинальный инстанц GLOBAL в замыкание
2) создать Harmony Proxy Handler с реализацией ВСЕХ перегружаемых методов
3) передать в качестве опционального аргумента оригинальный инстанц GLOBAL из замыкания
только после этого у Вас не будет циклического переполнения стэка, и вообще Раэйн сказал что хочет все что можно переписать на JS из ядра node.js поэтому все функции ядра viсe-versa являются высокоуровневыми абстракциями. (например тот-же process.nextTick) ;)
Вообще-то нет, и если уже на то пошло — то не ноды, а движка V8, т.к. политика Joyent — не вносить патчи в V8, даже если кто-то вносит такой коммит — то его не принимают, и отправляют его на googlegroup чтобы был патч для основной ветки V8 на офф. сайте — при условии что это критический баг.
console.log.toString() // 'function () {\n process.stdout.write(util.format.apply(this, arguments) + \'\\n\');\n}' где process ссылается на GLOBAL
Для корректной перегрузки GLOBAL Вам нужно сделать 3 действия:
1) скопировать оригинальный инстанц GLOBAL в замыкание
2) создать Harmony Proxy Handler с реализацией ВСЕХ перегружаемых методов
3) передать в качестве опционального аргумента оригинальный инстанц GLOBAL из замыкания
только после этого у Вас не будет циклического переполнения стэка, и вообще Раэйн сказал что хочет все что можно переписать на JS из ядра node.js поэтому все функции ядра viсe-versa являются высокоуровневыми абстракциями. (например тот-же process.nextTick) ;)
Вообще-то нет, и если уже на то пошло — то не ноды, а движка V8, т.к. политика Joyent — не вносить патчи в V8, даже если кто-то вносит такой коммит — то его не принимают, и отправляют его на googlegroup чтобы был патч для основной ветки V8 на офф. сайте — при условии что это критический баг.
0
кстати по поводу
было глупо т.к.
это особый тип и его нельзя заменять — можно только оборачивать через Proxy
например:
GLOBAL = {a: 1}
было глупо т.к.
typeof(GLOBAL) // "[object global]"
это особый тип и его нельзя заменять — можно только оборачивать через Proxy
например:
this.GLOBAL["a"] = 1 // 1
a // 1
0
Ну понятное же дело, что global :) Мы же сейчас говорим об подмене GLOBAL проксей — те попытке подменить/пропатчить объект на который ссылается GLOBAL.
По старой спеке первый параметр прокси target — это просто хранилище полей для прокси. Прокся его не пропатчивает и при работе с ним напрямую ничего не меняется. В новой все вроде бы так и осталось.
Show me the code ;-) пока я не верю в возможность влияния прокси на Identifier Resolution
По старой спеке первый параметр прокси target — это просто хранилище полей для прокси. Прокся его не пропатчивает и при работе с ним напрямую ничего не меняется. В новой все вроде бы так и осталось.
Show me the code ;-) пока я не верю в возможность влияния прокси на Identifier Resolution
0
в этом случае суперглобальные объекты будут обрабатыватся через Harmony Proxy handler
0
Интересно. instanceof только с кроссфреймовыми запросами себя так ведёт, или ещё в каких то ситуациях? Это баг реализации или это следует из стандарта?
Необходимость кроссфреймовых JS запросов очень редка, так что знать полезно, но бояться из за этого пользоваться instanceof не стоит.
Необходимость кроссфреймовых JS запросов очень редка, так что знать полезно, но бояться из за этого пользоваться instanceof не стоит.
Это требование зависит как от кодстайла так и от алгоритма. Однозначано так говорить не хорошо.Не настаиваю, на том что это лучший вариант, это лишь дополнение к instanceof для проверки пустых типов. Хотя в конечном итоге всё сводится к кодстаилу и конкретной ситуации.
Вы про какие объекты сейчас говорите?Да, похоже преувеличил, имея в виду общий случай, в которой дело имеется либо со свойствами объекта «this.var», либо с локальными переменными, объявленными и используемыми в пределах одного экрана, когда нет необходимости помнить была ли переменная объявлена. Реальный случай, когда действительно может остро встать проблема ошибок из-за не объявленных переменных — это десяти экранные функции со множеством переменных, или глобальная область определения, в которой можно воспользоваться «window.var».
тут важно понимание операций Identifier Resolution и Property Accessors, а не их последствий :)Теория и практика — две части целого.
0
Это баг реализации или это следует из стандарта?Это фича. instanceof использует цепочку прототипов, которая в разых фреймах разная. «Адреса» объектов разные, а функционал одинаковый.
Необходимость кроссфреймовых JS запросов очень редкаНе спорю. Лучше вообще использовать Array.isArray ;-)
0
Интересно. instanceof только с кроссфреймовыми запросами себя так ведёт, или ещё в каких то ситуациях?
Если писать UserJS плагины, то тоже такая фигня. В хроме есть
window.Array
и unsafeWindow.Array
. И внутри приложения используется именно второе. То есть если вы хотите написать плагин — вам придётся использовать unsafeWindow.Array(1,2,3)
вместо [1,2,3]
. 0
www.destroyallsoftware.com/talks/wat
Советую посмотреть, в этой короткометражке вы узнаете чему равно
и прочие радости яваскрипта :)
Советую посмотреть, в этой короткометражке вы узнаете чему равно
{} + {}
{} + []
[] + {}
[] + []
и прочие радости яваскрипта :)
-1
(function(){
var uscope = window, //window['utils'] = (window['utils']?window['utils'] : {}) ,//
types = "Boolean Number String Function Array Date RegExp Object".split(" "),
is = function (type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type;
};
for(var i=0;i<types.length;i++)
uscope['is'+types[i]] = (function( type ){
return function( obj ){return is( type, obj )};
}( types[i] ));
}());
и получаем методы:
isBoolean
isNumber
isString
isFunction
isArray
isDate
isRegExp
isObject
если желаем — то в window.utils…
одна беда — при разработке использовать не удобно, среда их «не знает», т.к. они генерятся в runtime
+1
За разъяснениями по таким вещам ->хорошо ходить на MDN. И стандарты упоминают, и совместимость, не только со своими продуктавми
0
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Подводные камни JavaScript