Pull to refresh

Comments 97

Детство кончилось. Пришло время прекращать шалить!
> [] + []
""
> [] + {}
"[object Object]"
> {} + []
0
> {} + {}
NaN
А ещё:

> { key: "value" }
"value"
В последних двух случаях фигурные скобочки это code blocks.
Всё просто и понятно же.
Вообще то, это Object
> p = { key: "value" }
Object {key: "value"}
> p.key
"value"


> var p = {}
undefined
> p
Object {}
В данном случае это не Object

{
  key:
    "value"
}

{} — code block
key — label
value — строка
что с вами?
> p = { key: "value" }
Object {key: "value"}
> typeof p
"object"
> typeof {}
"object"
Вместо того, чтобы препираться, лучше бы попробовали запустить
 {key: "value"}
без присваивания.
прошу прощения, не понял предыдущего оратора…
Вообще, чтобы понять, что происходит в этих странных сложениях и почему получаются такие результаты, нужно знать несколько моментов.
Первый: в js можно складывать только числа и строки. При сложении других типов данных происходит попытка конвертировать переменные или в число, или в строку.

Таким образом, сумма двух массивов — это конкатенация двух пустых строк, и это логично:
> [].toString()
""
> [] + []
""


Второе сложение действует аналогичным образом:
> a = {}
Object {}
> a.toString()
"[object Object]"
> [] + {}
"[object Object]"


Третье и четвертое сложения вводят в заблуждение. Казалось бы, от перемены мест слагаемых сумма не меняется, и мы пытаемся снова сложить объект с массивом, но интерпретатор js воспринимает первую пару фигурных скобок, как Code Block, и игнорирует его.

Остается +[]. Плюс в данном случае является унарным оператором и ведет себя эквивалентно Number([]).
Как ниже описал cyberface, получается, что 3-е и 4-е сложения эквивалентны соответственно:
> {} + []
0
> + []
0
> Number([])
0
> Number([].toString())
0
и
> {} + {}
NaN
> + {}
NaN
> Number({})
NaN
> Number({}.toString())
NaN
Казалось бы, от перемены мест слагаемых сумма не меняется

"a" + "b" == "ab"
"b" + "a" == "ba"


Так что очень даже меняются.
Я не JS-ниндзя, но, по-моему, это всё объясняет:
> p = {key: 'value'};
Object {key: "value"}
> p
Object {key: "value"}
> {key: 'value'}
"value"
> {'value'}
"value"
> {key1: 'value1', key2: 'value2'}
SyntaxError: Unexpected token :
Это таки лейбл
{label: if(true){console.log("it's a label!")}} 

Т.е.
{} + []

Эквивалентно
+ []

Что в свою очередь эквивалентно
 + Number([])

Number([]) в свою очередь вызывает toString у массива (потому что это не примитив) что вернет пустую строку, получаем
 + Number('')

а Number('') это 0
ч.т.д.
> typeof {label: 3+3}
"object"

Тут же присваиваем переменной
> p = {label: 3+3}
Object {label: 6}

> p
Object {label: 6}

> p.label
6


и typeof на {} говорит что это обьект.
> typeof {}
"object"
koshak, FanKiLL. Это разные конструкции.

{
  label1:
    "value"
}


Standard ECMA-262
5.1 Edition / June 2011
ECMAScript® Language Specification

{}Block
label1Labelled Statements
"value"String Literals

Это просто кусок кода, а не Object
{ // block
  console.log('before label');
  label1: // label
    console.log('after label');
    
    for (var n = 0; n < 10; n++) {
      console.log(n);
    }
}


var p = {
  label1: "value"
};

{} — В данном случае Object Initialiser.

Да я уже понял свою ошибку.
Зачем вообще нужен этот code block если он не делает свою область видимости?
Он используется повсеместно для группировки выражений

Банальный пример для if и for без code block
if (true)
  console.log('action');

for (var n=0; n<10; n++)
  console.log(n);


с code block
if (true) {
  console.log('action 1');
  console.log('action 2');
  console.log('action 3');
}

for (var n=0; n<10; n++) {
  console.log(n);
  console.log('some action');
}
для if и for понятно и так, зачем его использовать как в примере с которого всё началось.
Я имею ввиду просто code block, вводит в замешательство.

var a = 3;
var b = 4;
{
  a = 50;
  b = 50;
}
alert(a + b); //alerts 100
(function () {
    "use strict";

    let a = 123;

    {
        let a = 42;
        console.log(a); // 42
    }
    
    console.log(a); // 123

})();

var a = 3;
var b = 4;
{
  var a = 50;
  var b = 50;
  var c1 = a + b
  console.log(c1); // 100
}
var c2 = a + b
console.log(c2); // 100
Вы хоть сами проверяйте что пишете, {} не создают новую область видимости и в вашем случае будет 100, 100;

вариант выше работает потому что там объявление через let а не var/
Про то что не создаётся область видимости я и писал выше и спросил зачем этот блок используют?
не создаётся область видимости

Как не создаётся, если я показал, что создаётся?
То что вы показали, не работает в нынешней версии javascript. Ваш пример у меня вообще не запустился под хромом.
Да и если вы не заметили в комментариях к коду рядом с console.log явно прописано //100 так что я явно проверял что запускал, просто вы не внимательно читаете.

let не работает в нынешней консоле хрома и появится только в JavaScript 1.7.

Я к тому, что тот кусок кода с которого мы начали {key: "value"}
легко принять за объект или кусок json. И сам javascript на запрос что же это typeof {key: "value"} говорит что это объект.
Показал, что простой блок не создаёт свою область видимости, как я писал выше в своём комментарии, так нафига его использовать?
UFO just landed and posted this here
Выходит, все-таки Мocha.
Детство кончилось. Пришло время прекращать шалить!

Ну боян же ж. Да и кто додумался вообще плюсовать объекты? Что вообще вы ожидали получить?
Если не смотреть на конкретный пример выше, то перегрузка операторов для объектов может иметь вполне определённый профит. К примеру, в Дарте:

class Point {
  num x, y;

  Point(this.x, this.y);

  operator +(Point point) => new Point(x + point.x, y + point.y);
}


ES7 WIP: Value Objects Operators Overloading
При плюсовании двух массивов, я ожидал бы конкатенации. Во всяком случае, в языке, где плюсом конкатенируются строки.

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

А какой именно конктенации? С удалением дублирующих, или нет? А почему именно конкатенация? А от минуса что вы ожидаете?
Отсутствие перегрузки оператора — решение и они его приняли не случайно.
Такой же конкатенации, как у строк. Разумеется, без удаления дублирующих, поскольку обычная операция добавления к массиву его не производит.

Перегрузка оператора тут совершенно не при чем, потому что речь идёт о стандартном типе языка. Вы же не жалуетесь на плюс для конкатенации строк, которые суть массивы символов — так почему же такая дискриминация по отношению к массивам объектов?

И, кстати, я предложил на выбор два логичных варианта вменяемой семантики — или конкатенации, или сообщения об ошибке вида «данная операция неприменима к объектам этот типа». Но никак не молчаливое возвращение пустой строки.
Вы же не жалуетесь на плюс для конкатенации строк


Жалуюсь. Но коли уж он работает для строк, то и для объектов должен.
Только «без удаления дублирующих» — это как? Если в объектах два элемента с одним ключом, то с какими ключами они должны быть в сумме?
Там речь шла конкретно о массивах — [] + []. Для них я бы ожидал [1,2,3] + [4,5,6] -> [1,2,3,4,5,6]. Для обычных объектов лучше все-таки кидать исключение, потому что там семантика несколько непонятна (обычные ключи еще можно скомбинировать, но что делать с прототипами?).
Учитывая, что строка практически везде всеще массив под-капотом, то да, я ожидаю конктенации без удаления дублей.
> [] + {}
"[object Object]"
> {} + []


Этот результат получатся сугубо из-за выполнения в консоле.
А вообще довольно таки ожидаемый ответ будет — '[object Object]' в обоих случаях
Печально что такой непродуманный и сложный для понимания язык захватил мир.
А теперь мы вынуждены его учить и любить, невзирая на все его недостатки.

Эх, если бы у Брендона Айка было бы больше 10 дней, может быть все было бы куда приятнее.
>> сложный для понимания язык
Программировать хорошо сложно на любом языке. Это требует опыта, глубоких познаний в предметной области, знания матчасти, плюс личные качества программиста. А начать писать <что-нибудь> на JS все же намного проще, чем на многих других языках.
Вопрос в том, сколько граблей разложено в траве. В JavaScript и PHP их просто дохрена, в Python и Ruby их совсем мало.
Согласен.
И всегда хочется тратить время на изучение крутых и удобных фичей языка, а не на изучение его граблей.
Если должным образом изучить грабли, можно ими пользоваться по прямому назначению. Вместо того чтобы наступать на них.
В любом топике найдется человек, говорящий что %subject_lang% ужасен, а %another_lang% просто няшка. Но вся суть в том, что нет плохих и хороших языков, есть плохие программисты и использование языка не по назначению — всё остальное пустая болтовня.
Ну вот и надо использовать JS по назначению, а именно написание простеньких скриптов для браузере, так нет же, его сейчас везде засовывают, из-за того что людей знающих его очень много. Мне кажется это ни к чему хорошему не приведет.
У популярного (может быть слово «универсального» тут тоже подходит) скриптового языка по дефолту должно быть много применений. Для JS конкретно мне пришел в голову Photoshop — там есть встроенный движок (с преферансом и поэтессами), однажды довелось воспользоваться — удобно. Хорошее примеение JS нашли Qt Quick — очень лаконично и удобно. Так что не стоит ограничивать области применения языка там, где он нашел наибольшее применение. С другой стороны — я не сторонник использования JS как first class citizen в win8, например, или gnome.

По моему мнению в идеале на одном скриптовом языке должно быть можно писать и shell-скрипты, и подобие makefile'ов, и в конктретных программах свои сценарии.
У JS есть самый крутой на данный момент потенциал/фича, он работает почти в любом браузере без лишних плагинов и на серверной стороне + HTML/CSS позволяют строить интерфейс любой сложности (хоть flat, хоть 3D, хоть вектор). И использовать эту возможность только для снежинок на хомяке перед НГ по меньшей мере глупо.
Похоже, JavaScript сейчас-как Си в 80-е. Можешь на нем не писать, но читать и понимать- обязан.
UFO just landed and posted this here
Так в том-то и драма, что изначально на заре веба нужен был простой скриптовый язык. «Серьёзным» языкам там делать было нечего в те времена. А когда уже появился запрос на серьёзные веб-приложения, то выяснилось, что из альтернатив только Flash (Java фактически выдавлена). Но даже его всеми силами пытаются выпилить из веба, т.к. вся инфраструктура заточена под JavaScript. Т.е. дело не в том, что JavaScript лучше Flash-а или Java (они лет 10 умели и умеют больше, чем сейчас JavaScript). Просто так исторически сложилось. Когда его внедряли никто не думал, что будет запрос на большие приложения. Подобные проблемы решали флэшовые или явовые плагины.
И вот мы сейчас мы имеем язык, который изначально задумывался для простой интерактивности, и на котором пытаются писать большие приложения, просто потому, что уже есть огромное количество дешёвых разработчиков на нём, и есть браузеры, которые не то, что новые языки не могут добавить, они даже со стандартами не всегда дружат.
UFO just landed and posted this here
Вот об этом и речь. Что те, кто должны сесть и договориться, либо жуют сопли, либо пилят альтернативы: Дарт и ТайпСкрипт. Простым разработчикам остаётся работать с тем, что есть. От этого острое ощущение какого-то грядущего… как бы это по мягче сказать… нехорошей ситуации, короче.
UFO just landed and posted this here
UFO just landed and posted this here
непродуманный и сложный для понимания
Даже авторитетные JavaScript-евангелисты типа Дугласа Крокфорда и другие, постоянно говорят о принципиальных архитектурных просчетах в этом языке. Не было бы этих просчетов, не возникали бы постоянные попытки исправить эти дефекты разного рода синтаксическим сахаром типа CoffeeScript, не появлялись бы библиотеки упрощающие тоже ооп-наследование.

А если посмотреть на прототипный механизм ооп-наследования в JavaScript. Я постоянно сталкиваюсь с тем, что программисты не могут до конца понять и прочувствовать как он работает, или используют его неправильно. Вот в языках типа Java или PHP, наследование очень простое и понятное, все его прекрасно понимают.

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

А начать писать <что-нибудь> на JS все же намного проще, чем на многих других языках.
Если только вы говорите о приложениях типа Hello Word или о простеньком управлении веб-страничкой. А если речь идет о каком нибудь приложении состоящим из хотя бы нескольких 10-20 классов и сложными структурами данных, то я абсолютно не согласен.
По мне язык очень даже продуманный и легкий для понимания. Все интуитивно понятно.
Когда пишем а = obj.property и obj.property = a совсем не очевидно, что obj.property может адресовать разные куски памяти, а может и одинаковые.
Четырем человекам это очевидно? :)
А можно попросить ссылку, где бы Крокфорд говорил о принципиальных архитектурных просчетах в JavaScript? Спасибо.
Ну вот тут www.youtube.com/watch?v=v2ifWcnQs6M введение в JavaScript с нуля, где он очень толково рассказывает о языке. Здесь он именно дает правильное понимание языка, а не кривое, как у многих других авторов.
Вроде в этом ролике он поминает несколько раз о подобных просчетах.
А уточните, пожалуйста, конкретное время, где Крокфорд говорит об архитектурных просчетах в JavaScript. Спасибо.
Не… там лекция на 2 часа, мне долго искать. Но про маразмы с this и проблемы с областями видимости, которые легко приводят к ошибкам, он там точно говорил. Про реализацию ооп, не помню, может быть просто говорит что она иная и идет своим, иным путем, который плохо понятен программистам из классических ооп языков.
Главное что он толково объясняет как всем этим пользоваться и на наступать на архитектурные грабли.
Т.е. вы предлагаете мне два часа поискать, при том, что вы даже не уверены, говорил ли он что-то об архитектурных просчетах или нет?
Вот его книга: JavaScript: The Good Parts
Первое предложение в аннотации книги:
Most programming languages contain good and bad parts, but JavaScript has more than its share of the bad, having been developed and released in a hurry before it could be refined.
Bad parts != принципиальные просчеты в архитектуре.
например, typeof null == 'object' — это неприятно, но никак не «принципиальный просчет в архитектуре».
В JS куда меньше архитектурных просчетов, чем в большинстве других языках программирования, но typeof null == 'object' именно архитектурный просчет, который безуспешно пытались исправить.
«This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.»
sarcasm
А по-моему надо было включить этот фикс, потому что typeof something == 'object' — это говнокод какой-то, и пусть все говнокодеры помучились бы и переписали нормально свои поделки.
/sarcasm
Проблема с этим языком в том, что он ворвался на рынок слишком быстро и так же слишком быстро был стандартизирован. Так что большинство его недостатков связаны не с текущей реализацией, а находятся в спецификации. Стандарт указывает делать это неправильно. А это просто ужасно. Но ситуация именно такова. В 1999 году развитие этого языка замерло, все должны были его забыть, и он должен был умереть. Но вместо этого совершенно случайно возник Ajax, и теперь JavaScript — самый важный язык программирования в мире.
И теперь мы думаем, что должны его как-то исправлять. Это нужно было сделать еще в 2000-м, но тогда этого никто не сделал, поскольку на него тогда никто не обращал внимания. Теперь же это сделать очень сложно.

Дуглас Крокфорд. Кодеры за работой. Размышления о ремесле программиста
Крокфорд вообще регулярно заблуждается. И часто то, что он называет хорошими практиками есть плохими. Не стоит все его слова воспринимать как истину в последней инстанции.
Нуууу… как Вам сказать… Вот МС делает TypeScript, вот Гугл делает Дарт. Вот де-факто, вместо использования нативных методов для работы с DOM, повсеместно используется JQuery. Это всё наводит на грустные мысли, что с большими веб-приложениями у JavaScript-а проблемы.
Хотя сам по себя язык интересный и прекрасно подходит для написания небольших скриптов.
Методы для работы с DOM — не часть стандарта ECMA-262.

Тогда уж надо навестись на грустные мысли о W3C. Даже если посмотреть текущий драфт, не заметно, чтобы стремились догнать и перегнать что-то высокоуровневое вроде jQuery. Такой цели похоже вообще не стоит.

Хотя я тут и не вижу ничего особо грустного. Почему бы и не иметь какие-то «маст хэв» (хоть и не стандарт) либы или фреймворки?
Никто же не говорит, что у Ruby проблемы с веб-приложениями, потому что повсеместно используется Rails?
Да, конечно, методы работы с DOM не часть стандарта. Но это часть инфраструктуры. Работа с DOM — это одна из важнейших задач JavaScript-а. И что? Как Вы сказали, даже цели не ставятся что-то улучшить и поправить. Людей это вообще не коробит. Ну, подумаешь, что разработчикам неудобно.

И да, у Консорциума большие проблемы. Настолько большие, что была создана WHATWG. Причём создатели прямо заявили, что это ответ на медлительность W3C.

В принципе ничего плохого в обязательных библиотеках нет. Вопрос лишь в том, зачем они нужны? Если речь идёт о каких-то сложных компонентах, которые делаются поверх базовых возможностей, то это одно. А если потому, что разработчики браузеров не могут обеспечить стандартизацию API, и он сам по себе неудобен, то это совсем другое. Может лучше, сделать удобные методы работы с DOM?
UFO just landed and posted this here
Вы считаете автовставку точки с запятой принципиальным архитектурным просчетом языка?
UFO just landed and posted this here
А если посмотреть на прототипный механизм ооп-наследования в JavaScript. Я постоянно сталкиваюсь с тем, что программисты не могут до конца понять и прочувствовать как он работает, или используют его неправильно. Вот в языках типа Java или PHP, наследование очень простое и понятное, все его прекрасно понимают.

Я думаю, это не из-за сложности прототипного механизма наследования. Просто везде преподают классическое ООП и у новичков JS возникает небольшой диссонанс.
Объектную модель JS можно сравнить с таковой в ANSI C. В последнем тоже нет объектов, зато есть структуры и макросы, через которые можно реализовать ООП. Но как только появился C++, он сразу же порвал чистый C, т.к. кодить на нём не в пример удобнее.
Вот так же и с JS. Его объекты — это те же структуры. Просто примитивные хэш-таблицы, не более. И, как и на структурах C, на них можно реализовать наследование, классы и кучу всего прочего. Но гораздо удобнее, когда всё это уже встроено в язык. Потому и появились TypeScript/CoffeeScript. Последний уже начинает вытеснять JS, по крайней мере на Stackoverflow я всё чаще наблюдаю, как на вопросы по JS отвечают кодом на CoffeeScript, что всегда вызывает бурю возмущения в комментариях.
… CoffeeScript. Последний уже начинает вытеснять JS

Вы несколько преувеличиваете :)
Разумеется, есть хорошие и плохие языки. Если они осмысленно разные, то эта разница в том числе может иметь и такое значение. И имеет. Хороший язык — тот, на котором у среднего программиста получается более читаемый и понятный код. Чем больше в языке часто встречающихся граблей, тем он хуже, особенно если эти грабли не компенсируются фичами или скоростью (как в плюсах).
Хороший язык — тот, на котором у среднего программиста получается более читаемый и понятный код.

А я то дурак всегда думал что читаемы и понятный код зависит от программиста, а хорошесть языка от качества решения поставленой задачи. Ну буду теперь выбирать ЯП по красоте кода.
Читаемость и понятность кода зависит и от языка, и от программиста. Если язык плохой, то хорошему программисту приходится больше трудиться, чтобы обойти все грабли и написать хороший код (и, соответственно, у него остается меньше времени на другие задачи).

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

Утвержать на хабре что-то опасно, могут налелеть и заклевать… Но вообще да, (почти) все машины хорошо ездят для своего времени/цены/характеристик и многое (не всё) зависит от водителя — не думаю что болид формулы-1 будет отлично кататься с водителем маршрутки по раздолбаных дорогам окраин области, в то время как раздолбаный старый внедорожник с опытным водителем и горы свернуть может. Что касается программирования, некоторые любят сами себе ставить грабли или слепо следовать патернам и тут уже от языка ничего не зависит. Или для JS навешать гору плослоек, а потом вопить в каждом топике что JS медленный язык, гавнокодя по сути не на JS, а на очередном «фреймворке», внтури которого непонятно что и непонятно зачем.
В любом случае в контексте данного топика о JS реальных альтернатив ему нет, поэтому говорить о качестве этого языка пока бессмыслено.
А я то дурак всегда думал что читаемы и понятный код зависит от программиста

На брэйнфаке как не старайся, читаемый код не получишь :)
Теперь трахаться с javascript можно совершенно легально!
UFO just landed and posted this here
Я начинал знакомство с js, как и многие сейчас, с jQuery. Точнее, я тогда уже знал основы js, но очень плохо.
Тогда мне этого вполне хватало, местами казалось удобным, местами нет, но когда уходишь чуть дальше от jQuery, возникало постоянное недопонимание. Потом захотелось делать заметно более динамичные страницы, появился проект, который по своей архитектуре задумывался как одна страница с переключаемыми областями (можно было извратиться и сделать перезагрузку всего, но это бы отвлекало и мешало оператору). Выбор пал на angular.js. Пришлось подучить и сам java-script. Ох, как я сейчас об этом не жалею. Сначала он пугает, отталкивает своей кажущейся нелогичностью в некоторых местах человеку, который до этого писал на C# несколько лет. Особенно шаблоны рвало местное наследование через прототипы и переодически выскакивающие баги на пустом месте (конечно место не пустое, а в прямом виде мое недопонимание языка).
Шли месяцы, и я осваивал js все больше, и с каждым днем он затягивал меня все глубже. Я проникся духом и идеей языка. Сейчас пишу сервис (вернее, часть сервиса), который отображает трехмерные графики (three.js), по некоторым причинам кроме этой библиотеке я не могу юзать больше ничего. Поэтому пришлось плотно познакомиться с vanila.js и я очень рад этому. Сейчас же даже делаю курсовую по машинному зрению на этом языке. Все очень удобно, логично, прозрачно. Возможность отладки вживую, изменения кода прямо на странице (когда думаешь, можно ли так сделать или нет — забил в консоль и все. Причем можешь использовать переменные, до которых можешь дотянуться) очень приятная. Замыкания — вообще просто философия, которую хочется тянуть везде, куда только можно.
У меня пока к нему только одна притензия — скорость работы. Но такова цена за удобство.
ИМХО — пока используешь его как инструмент, js не нравится. Когда начинаешь «жить им», вникаешь в его парадигмы и идеи — можешь закрыть глаза и на недостатки, все равно будет хотеться все писать на нем. Впрочем, это свойственно всем языкам (правда php меня только раздражает, хотя на нем я больше писал).
А да, еще дико бесит отсутствие строгой типизации. Да, это местами хорошо, а местами дико бесит. Так, по глупости напишешь var a = 1 + 1 и получишь a = 11;
Для типов можно использовать TypeScript, типизация конечно получается только compile time, т.е. в коде вы никак не сможете узнать, например, что за интерфейс у переменной, но даже это будет как воздух тем кто привык к типам.
var a = 1 + 1 и получишь a = 11;

wat? Проверил в консоли: а = 2
Ну что, JavaScript теперь готов нести ответственность? )
А в каком штате Америки изобрели JS? Ведь в некоторых из них совершеннолетие наступает с 21 года =)
Да, ещё три года, ему можно будет покупать алкоголь.
Sign up to leave a comment.

Articles