JavaScript е жена

Picture-71

JavaScript е жена. Понякога е отзивчивата, вършеща всичко любима, а понякога е нетърпимата, правеща каквото си поиска, нелогична в действията си красавица, която ви подтиква да се влюбите в нея. Ако любовта към жената минава през стомаха, то любовта към javascript тогава минава през много F*ck this shit. Накрая просто се жените за нея и… свиквате със чудатостите и.

Целта на следващите примери са обобщение на някой известни, и някои не толкова известни поведения на js в някои browser-и, които голяма част от хората свикнали с “цивилизовани езици”, смятат за странни. Повечето примерите са базирани на поведението на JS по ECMAScript 5.1 в browser среда.

javascript_1

Всичко е object

Или почти всичко, като изключим примитивите (String, Boolean и т.н.), които обаче пък имат object wrapper-и, от където идва и самото объркване, че всичко в js е object.
И тук човек си мисли, да сигурно всичко е object, като изключим да речем и null. Само че дори null е object.

typeof null // results in "object" 

Въпреки това, дефиницията за null е “тотална липса на смислена стойност”. Именно затова и

null instanceof Object // results in false

Така хем е обект, хем не е… та предполагам започвате да разбирате защо си позволих сравнението между js и нежния пол.

Undefined can be defined

Колкото и странно да звучи undefined, въпреки че е ключова дума в js, може да бъде дефинирана. Следния код е напълно смислен.

var pesho;
pesho == undefined; // results in true

Всичко е супер, до момента до който не решим че можем да присвоим стойност на undefined.

undefined = "Test";
var pesho;
pesho == undefined; // results in false;

Та въпреки че не сме дали стойност на pesho след сравнение с undefined резултата е false, просто защото преди това сме дали стойност на undefined – яко… Тази красотия се появява най – често при FireFox и най – лесно може да си дадете обяснение като отидете на сайта им и потърсите дали според тях undefined e ключова дума.

replace()

Тук, странностите са няколко. Нека да започнем с първата.

"gosho".replace("o", "a"); // results in "gasho" - the rise of a new hero

Може би очаквате replace да ви замени всички срещания на даден символ – не точно. Би могло да стане, но за целта трябва да използвате regex, което предвид “големите” regex познания при всички програмисти, прави тази функция доста приятна.

"gosho".replace(/[o]/g, "a"); // results in "gasha" - not as cool as gasho

Втората странност е възможността 2рия параметър на replace() да бъде callback. Спорно е колко често ще ви се наложи, но е добре да си имате едно на ум. Да речем в произволен текст искате да замените температурата от Фаренхайт към Целзий.

function f2c(str)
{
  var regexTest = /(\d+(?:\.\d*)?)F\b/g; // this will search for every number that ends with F (for Fahrenheit)
  function convert(str, p1)
  {
    return ((p1-32) * 5/9) + "C";
  }

  return str.replace(regexTest, convert);
}

f2c("Today is 60F"); // results in "Today is 15.5C"

easy_website

NaN е… число

Спомняте ли си колко абсурдно звучеше, че null е object. А колко по – странно е че NaN(“Not a Number – не е число”) всъщност е число. И за да е пълна приказката – NaN не е NaN :D Всъщност NaN не е равно на нищо. Единствения начин да разберете дали нещо не е число, е не като го сравнявате с NaN а като използвате функцията isNan().

typeof NaN; // results in "number"
NaN === NaN; // results in false

"pesho" === NaN // results in false
isNaN("pesho"); // results in true

Math.min() & Math.max()

Тази странност е по – лесна. Чисто и просто Math.min() е по – голямо от Math.max(), защото Math.min() връща +Infinity, докато Math.max() връща -Infinity.

Math.max() > Math.min() // results in false

Date

Когато Date се извиква като конструктор, връща обект, който е релативен спрямо 1 Януари 1970. Когато обаче параметър липсва, получаваме текущото време. Когато обаче извикаме Date като функция получаваме не обект, а стрингова репрезентация на текущото време.

var a = Date(); // results in string "Mon Apr 28 2014 13:33:23 GMT+0300 (FLE Daylight Time)"
var b = Date(0); // again results in string "Mon Apr 28 2014 13:33:23 GMT+0300 (FLE Daylight Time)"

var c = new Date(); // results in object of today - "Mon Apr 28 2014 13:34:27 GMT+0300 (FLE Daylight Time)"
var d = new Date(0); // results in object of 1970 - "Thu Jan 01 1970 02:00:00 GMT+0200 (FLE Standard Time)"

Length

Някои стойности по подразбиране също могат да бъдат малко подвеждащи. Да речем дължината на Function по подразбиране е 1. Докато дължината на Function прототипа е 0.

var a = Function.length; // results in 1;
var b = new Funtion().length; // results in 0;

Още за ключовите думи

Като цяло странностите с ключовите думи не са 1 и 2. Следващата която ще разгледаме е ключовата дума class. Да си представим следната ситуация:

var a = {
   class: "Human",
   name: "Gasho"
};
a.class // results ???

Ако се замислим най – логичното е ако пробваме да достъпим пропъртито class на обекта а, да получим резултат “Human”. Но отново зависи от случая. Chrome, FF и Opera отчитат class като ключова дума, но го приемат като възможно пропърти (какъвто е и нашия случай). Но познайте кой browser не изброих. IE отново си имат собствено мнение. Там още декларацията ще ви гръмне със “Expected identifier, string or number”.

name

1337545695905_5722519

name е readonly пропърти, което всяка функция има. Интересното е, че като такова би трябвало да гърми ако се опитате да го промените. No.

function gasho() { };
gasho.name; // results in "gasho"

gasho.name = "pesho"; // should throw error??
gasho.name; // results again in "gasho"

toString

Много често искате да стрингосате дадено число. Някои могат да решат, че 3.toString() е достатъчно. Само че това ще гръмне със синтактична грешка. От друга страна 3..toString() ще ви върне резултат “3”, понеже разчита 3. като 3.0, което вече стрингосано води до “3”. Естествено 3…toString() обаче също ще гръмне понеже няма число с две точки :).

Говорейки за toString един от най wtf сценариите е следният.

2 == [[[[2]]]]; // results in???

Привидно масива от масиви от масиви (и т.н.) е несравним със число. Само че в случая js ги стрингосва и 2те и така ги сравнява и резултата от сравнението е true.

Последното нещо свързано със стрингосването, на което ще обърна внимание е следния вариан:

"5" + 3; // results in 53
"5" - 3; // results in 2

Причината за това е че + оператора се използва за обединяване на стрингове и в случая числото 3 автомагически се стрингосва и се залепя до 5тицата. Докато при оператора “-” се извършва обратната операция и числата се възприемат като такива.

Математически операции

Като цяло js не е език на който можете да разчитате на точни сметки. Нито със малки, нито със големи числа.

var a = 111111111111111110000 + 1111; // results in 111111111111111110000

var b = 0.8 - 0.6; // results in 0.20000000000000007

No idea

Още един доста интересен случай. В ситуацията обаче ако трябва да съм честен и аз не съм много наясно какво точно се случва.

1 + - + + + - + 1; // results in 2

Заключение

Както виждате и сами може би javascript наистина е жена. За съжаление обаче може би обърнахме внимание само на негативните качества, докато се надявам следващия път (дано е скоро, че с това темпо на писане на постове…), ще обърнем внимание на по – сложните сценарии като ще намесим scope, arrays, constructors и т.н. и ще разгледаме защо все пак в крайна сметка се влюбваме в javascript.

Чувствайте се свободни да коментирате и странности на които вие сте попадали.

1333216027829_9197583


14 Responses to “JavaScript е жена”

  1. Мая says:

    В “No idea” това, което се случва, е че математическите оператори “+” и “-” при наличие само на един аргумент считат втория за 0, т.е. все едно изразът ти е
    1 + 0 – 0 + 0 + 0 + 0 – 0 + 1;

  2. Мая says:

    Всъщност горният коментар не е точен, просто единственият знак, който се изпълнява като оператор, е първият (+ът), а всеки следващ отдясно-наляво се прилага върху последната единица, и понеже минусите са четен брой, тя се оценява отново до 1, и накрая изразът се свежда до
    1 + 1

  3. Teo says:

    Благодаря ти, Павка!!!

  4. Цветан says:

    Благодарим ти, Павка!

  5. Добромир says:

    Принципно различните браузъри си имат допълнителна имплементация на част от нещата – за тест, “”.replace.toString() под FireFox ще издаде интересна имплементация, виж го.
    Иначе, по дефиниция, ако първият параметър подаден на String.replace е string, то трябва да се замени само първият срещнат – http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.11

  6. Благодаря ти, Павка™!

  7. Ето и някои от една моя лична подборка по същата тема: http://blog.marudina.net/?p=266

  8. JavaScript e жена … свободна от предрасъдъци, поради това нелогична в “граничните задачи”, но и креативна! Не стоят ли нещата по подобен начин и с други два езика – PHP и Basic.? Креативност и жизненост срещу правилата и каноните…хубава тема за размисъл, благодаря!

  9. Очакваме продължение с положителните страни на “жената” ;)

  10. tsigularoff says:

    В добавка на казанато от Maya ако последният пример го променим леко :

    1 + – + + + – – – 1 // 2

    т.е. имаме четен брой оператори, последният оператор от ляво на дясно се приема като знак на числото.

  11. Петър Й. says:

    Благодаря за статията.
    Тя е наистина още една мотивация за моята любов към джаваскрипт.
    Преди пишех на С и всичко беше толкова скучно. Оправящ една грешка, той ти казва “хайде давай, че има още 100”. Тук само го отварям, гледам кое не му е харесало, оправям го и спи града. А и най-хубавото – няма указатели – просто език мечта!

  12. Svetoslav says:

    Въпрос : защо
    let sentence = “This is a string”;
    console.log(sentence[10]); ми връща само 1 символ ? “s” ?

    • Pavel Kolev says:

      Ами защото може да разглеждаме стринговете като масив от символи :) в случая десетият елемент от стринга е символа “s” (първата буква на “string”)

Leave a Reply

Your email address will not be published. Required fields are marked *