As For JS
3.45K subscribers
123 photos
12 videos
4 files
358 links
As For JavaScript...
Обсуждения — @AsForJsTalks
Download Telegram
Обязательно посмотрите Flow/Поток, полтора часа мимимишного рафинированного удовольствия

Искать перевод - ненужно. Там перевод не нужен.

https://www.youtube.com/watch?v=VYZLQR0jLjs
13👍5👌3
Чтобы почитать про программирование.

Очень рекомендую к прочтению старую книжку McConnell-а "Совершенный код"

Она будет Вам интересна как с точки зрения проектирования приложения, так и с точки зрения того, как изменились взгляды на эффективное программирование.

Чтобы познакомиться с материалом вот вам ссылка, которая будет активна сутки.

Если Вам понравится книжка - купите ее.

Обновил ссылку.
https://murych.com/media/books/js/Makkonnell_S_Sovershenny_kod.pdf
👍26🙏13🔥1🐳1
Задачка на внимательность

Что будет выведено в консоль?
"use strict";
[1,2,3]
.map(
()=>{ console.log(this); }
, {'this': 'is'}
)
👍10
https://t.me/AsForJsTalks/90966
Почему в JS нет переменных

О моем отношении к термину переменная и терминологии в целом

Єффективность общения программиста с другим программистом для случая их профессиональной деятельности, зависит от того насколько язык который они используют понятен для них обоих.

Чем сложнее и глубже термин - тем эффективнее их общение, в случае если они его понимают одинаково.

Например: .
если я Вам скажу TypeScript, то Вы меня поймете строго однозначным образом.
если я Вам скажу Promise (в контексте языка JavaScript) - Вы меня поймете однозначным образом.

НО
если в контексте языка JavaScript - я Вам скажу переменная, то Вы меня поймете в зависимости от Вашего уровня погруженности в тему.

Большинство расскажет что это некая коробочка, которая содержит в себе некое значение и шабаш.

В то же время, условный ДецПердец скажет - ты ебанулся не иначе. Никаких коробочек для значений в JS нет.

То есть мы не поймем друг-друга.
И разница в понимании того, что именно не так, будет прямо влиять на качество вашего программирования.


О перегруженности терминов
Эту проблему, обычно, решают на уровне спецификации - описывая Terms и Conditions. То есть то как следует понимать те или иные термины в рамках этого документа.

Например спецификация содержит термин Exotic Object. Что это такое?
Или что такое undefined? Из определения строго следует - что это особое Value (значение). Физически существующее значение, но не статус Identifier как многие думают.

В JavaScript, если Ваш идентификатор undefined - то это не означает его статус. Это означает что идентификатор связан с особым значением Undefiend. Равно как и Null.

В то же время в других языках, это может быть именно особый статус Идентификатора.


Что это значит для программиста? Это значит, что когда идентификатор === undefiend - мы проводим ровно туже операцию сравнения что и для идентификатор === 7; Что поведение этого идентификатора определено том же самым правилом, как если бы он был связан с любым другим типом. Он не имеет особого поведения.

Я как программист, знакомясь с JS и прочитав об этом в спецификации, сделал для себя совершенно очевидный вывод:
Если я хочу быстрый код, то мне лучше иметь, подобно тому как это делают в языке Ассемблера или Си, свои числовые константы, которые получают максимальную производительность. Тем самым избавив себя от лишней абстракции.


К чему тут переменные
Термин переменная никак не определен на уровне спецификации. НИКАК. Употребление слова variable касается только внутренней кухни самой спецификации.

Как работают Идентификаторы в JS?
Каждый Ваш идентификатор - это строковый ключ в обьекте (эта аналогия чрезвычайно близка к реальности). Где property этого обьекта содержит 32 или 64 битный адрес в памяти на структуру, которая описывае с чем именно связан идентификатор.

На уровне спецификации это описывается парой строчек - Reference Like. Мой рассказ про структуру и ссылку и биты - это из реализации V8 того самого Reference Like.

Как следствие вопрос - а где тут коробочки?
Если они и есть на уровне спецификации - то только для того, чтобы в них лежали ссылки.


Вернемся к разговору двух программистов. Если я пришел из Си и услышал слово перменная, которое никак не регламентируется на уровне спецификации JavaScript - я автоматом подумаю ПРО РЕАЛЬНУЮ КОРОБОЧКУ. Потому что в языке Си при компиляции, ваше число будет не какойто ссылкой на структуру в памяти - а рельаным его представлением либо в 32 либо в 64 либо в форме с плавающей точкой.

И я подумаю. О круто - переменная и число. Экономия память. Фаст перформанс. Кул кул.
И ахренею когда узнаю что это вранье. И в JavaScript все reference like.

Где это применяется? Пример.
У Вас строка в 1 мегабайт. Вы ее передаете в функцию. Вам говорят - там копируются по значению. И Вы как Си программист сидите такой и думаете - ипать копать, а как в функцию передать строку, чтобы не создать ее копию?

И вопрос этот у программиста возник именно потому что он думает что термин переменная с которым он пришел в JS не совпадает с тем как это есть в JS.
🔥24👍81👎1👌1
То есть терминология которая использовалась при общении двух людей ввела одного в заблуждение что привело к неэффективности его кода.


Почему в JS нет переменных
Они там коненчо же есть. Но они там существуют не в виде коробочек, как всем рассказывают, но в виде ссылочных типов. Если говорить совсем академическим языком - все переменные в JS это Shared Variables. или Shared Reference. В спецификации это называется Reference Like.

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


Вместо Игого
Есть ли в JS переменные - да есть.
Но это утверждение не имеет никакого смысла без пояснения - какая именно архитектура используется для формализации их работы. Потому, что без этой рашифровки, в программировании, с равным успехом переменные можно называть ЧпокиМоки и снова рассказать про мифические коробочки.
🔥191
Друзья. Я попрошу Вас быть максимально честным в этом опросе.
Он полностью анонимный и никто Вашего ответа кроме Вас видеть не будет.
Каким образом передаются параметры в функцию для Primitive Values (Number, String etc...)
Anonymous Quiz
57%
По ссылке
21%
По значению
8%
И так и так
14%
Я упырь
😁16
Я просто оставлю это здесь
История одного комита в type script compiller. от 2023 года.

Performance on TypeScript compiler
Runtime
Using the STR in this issue comment filed by TypeScript, using this TypeScript commit (because it predates their manual var downleveling),

The prototype CL saw an improvement of 2-3% (1.29s - 1.30s parsing to 1.26s - 1.27s).

To compare, manually downlev eling to var sees an improvement of 6% (1.29-1.30s of parsing to 1.22s - 1.23s)
.
цифры даны инженерами v8


Кому интересно почитать обсуждение
https://issues.chromium.org/issues/42203665

Документ от инженеров V8 про особенности работы let/const с упоминанием того самого комита и цифр.
https://docs.google.com/document/d/1klT7-tQpxtYbwhssRDKfUMEgm-NS3iUeMuApuRgZnAw/edit?tab=t.0

шаг и мат шароземельщикам.


К слову по итогам 23 года, инженеры V8 поделились тем что они сделали за год, где в том числе было сказано

Finally, we also made ES6+ JS code faster by eliding some redundant temporal dead zone checks for let and const bindings.


Что и обьясняет изменение цифр в оценке производительности с 10-15% которые я давал два года назад, до 5-10% сейчас.
🔥13😁94👍3🕊1
Это все еще не все.
Не смотря на то, что тема работы var/let/const для меня закрыта, и теперь за меня будут говорить инженеры v8, я анонсирую новый ахуху кейс при использовании let. Который всех снова поставит на рога.

Я сам его только что случайно открыл. Но я Вам его не покажу, потому, что у вас документов нету.

Все, в том числе и я, как остолопы тестировали издержки связанные с ThrowReferenceErrorIfHole, и никто не додумался посмотреть на то, как этот Hole инициализируется. А там, издержек в два раза больше


Кому нечем заняться - попробуйте угадать где проблема.
Вот код для теста.

function doAdd1( a, b ) {
var theThing = 1;
let theSummator = 0;
function doSum() {
for ( var i = 0; i < 10000; i++ ) {
theSummator += theThing + i;
}
}
doSum();
return theSummator;
}
😁9💔8🤯2😎2😍1
Использование var/let/const в примерах

Когда let/const не создаст никаких проблем с производительностью
let/const не создаст вам никаких проблем при условии, если вы их используется СТРОГО в рамках одного функционального окружения:
function doExampleWhereAllFineWithLet() {
function doCalculateCirlceArea( theRadius ) {
const PI = 3.14;
let thePower = 2;
return PI * theRadius ** thePower;
}
doCalculateCirlceArea( 10 );
}
doExampleWhereAllFineWithLet();

Оба идентификатора( thePI, thePower ), используются только в том функциональном окружении, в котором они заявлены.
Производительность этого кода будет на 100% идентична случаю, если бы мы вместо let/const использовали var.



Когда let/const начнут создавать проблемы с производительностью
Проблемы возникают тогда, когда объявленный идентификатор начнете использовать за пределами того функционального окружения в котором был объявление.
function doExampleWhereWeHaveProblemsWithLet() {
const PI = 3.14;
let thePower = 2;
function doCalculateCirlceArea( theRadius ) {
return PI * theRadius ** thePower;
}
doCalculateCirlceArea( 11 );
}
doExampleWhereWeHaveProblemsWithLet();

Оба идентификатора ( thePI, thePower ) используются в другой функции (функциональное окружение отличается от того, где они были объявлены)
В этом случае Вы получаете дополнительные издержки внтури функции doExampleWhereWeHaveProblemsWithLet
Глубина вложенности не важна.


Решение проблем производительности let/const через var
Решением проблем let/const, для случаев использования идентификаторов в окружениях отличных от тех где этот идентификатор был создан, является замена let/const на var.
function doExampleWhereWeResolveThroughVar() {
var PI = 3.14;
var thePower = 2;
function doCalculateCirlceArea( theRadius ) {
return PI * theRadius ** thePower;
}
doCalculateCirlceArea( 11 );
}
doExampleWhereWeResolveThroughVar();



Одно исключение для var
Замена let на var в случае, если идентификатор декларируется в глобальном окружении, напротив приведет к еще большим издержкам.

То есть код вида:
var PI = 3.14;
var thePower = 2;
function doCalculateCirlceArea( theRadius ) {
return PI * theRadius ** thePower;
}
doCalculateCirlceArea( 7 );



Будет работать медленнее чем:
let PI = 3.14;
let thePower = 2;
function doCalculateCirlceArea( theRadius ) {
return PI * theRadius ** thePower;
}
doCalculateCirlceArea( 8 );


Происходит это потому, что спецификация, для случая глобального окружения и variable statement, обладает своим особым поведением, которое создает дополнительные издержки: подобный идентификатор должен создать Property в Global Object. Что требует дополнительных издержек от Agent-а выполняешь го JS код.
Чего не происходит в случае let/const. Так как для них подобное поведение не определено.

var theVarThing = 1;
console.log( globalThis.theVarThing ); // 1
console.log( theVarThing ); // 1

let theLetThing = 2;
console.log( globalThis.theLetThing ); // undefined
console.log( theLetThing ); // 2
🔥30👍93😍2👀2❤‍🔥1👨‍💻1
Краткое ИГОГО тезисами:

1. Современный V8 вынужден тратить больше ресурсов на исполнения кода для let/const declaration.

2. Возникновение этих издержек СТРОГО связано с использованием идентификаторов, заявленных при помощи let/const в функциональном окружении, которое отличается от того где они используются.

3. Окружение создаваемое Block Statement (Declarative Environment) не создает лишних издержек. Все сказанное касается ТОЛЬКО функционального окружения.

4. let/const declaration не имеет никаких отличий от var в том случае, если заявленный идентификатор используется ТОЛЬКО в том же функциональном окружении где и был объявлен идентификатор.

5. var подобных издержек не имеет. То есть производительность let/const всегда либо равна variable statement либо хуже.

6. Для var существует одно исключение связанное с объявлением идентификаторов в глобальном окружении. Где var покажет худшую в сравнении с let/const производительность.

7. Не забывайте, что function declaration согласно спецификации, выполняет те же шаги что и variable statement. Из чего следует, что если вы используете function declaration в Global Environment - вы создаете ненужную нагрузку на Agent исполняющий ваш код.

8. На текущий момент (начало 2024), let/const медленнее var на 7% +-2;
На конец 2022 года, эта цифра была на уровне 15% +-5

9. Существуют еще дополнительные издержки возникающие на стадии Static Semantics для анализа кода с Let и Const. Все что описано ваше, касается только RunTime Semantics


Дополнительные детали в документе от инженеров V8
🔥37👍5😍2
Про void

Современный V8, игнорирует спецификацию void как таковую.
И преобразовывает любой код с void к такому, который исполняется без него, с полсдещуюей вставкой undefined

Например код
function doThing() {};

void doThing();


На уровне V8, код будет приведен к следующему байт коду:
CallUndefinedReceiver0 r0, [0]
LdaUndefined


Эквивалентом этому коду на языке JavaScript будет:
function doThing() {};

(
doThing()
, undefined
)



Вместо ИГОГО
Современный V8 игнорирует void как самостоятельный оператор, и заменяет его альтернативным взаимозаменяемым кодом.
То есть с точки зрения проивзодительности, в отличии от махровых времен, сейчас никаких дополнительных расходов на использования void нет.
Пишите сколько влезет. V8 за вас заменит его на undefined.
👍25👌5