Безпечне використання "з" у JavaScript

Практично кожен ресурс, що документує з , який я можу знайти, застерігає від його використання, головним чином тому, що якщо змінна не визначена, вона може мати непередбачувані ефекти.

Я хочу зрозуміти його, щоб я міг ефективно використовувати його - врешті-решт, він є з цією причиною. Навіть eval має свої незрозумілі використання!

So, with that in mind, let's say I want to delete all child nodes from an element, without using elem.innerHTML = "";

Чи буде безпечним наступне?

with(elem) while(firstChild) removeChild(firstChild);

Зверніть увагу, що на даний момент я не дбаю про читабельність, просто функціональність. Оскільки firstChild є властивістю, і removeChild методом, всі вузли елемента, це повинно бути добре, щоб використовувати з таким чином, чи не так?

Аналогічно, скажімо, я хочу встановити деякі стилі.

with(elem.style) {
    color = "red";
    backgroundColor = "black";
    fontWeight = "bold";
}

Оскільки всі ці властивості є об'єктом стилю (навіть якщо вони не визначені в таблиці стилів, вони є порожніми рядками), добре використовувати з , так?

Я щось відсутній, або це постійне попередження, щоб не використовувати з , подібне до того, що використовується для розширення PHP MySQL : захист від німих програмістів?

9
Я голосую за захист від зловживання
додано Автор zerkms, джерело
Будь ласка, перегляньте, перш ніж запитувати: точний дублікат Чи існують законні використання для JavaScript " "виписка? . Також пов’язано: Майбутнє з виступом у Javascript
додано Автор Bergi, джерело
Будь ласка, перегляньте, перш ніж запитувати: точний дублікат Чи існують законні використання для JavaScript " "виписка? . Також пов’язано: Майбутнє з виступом у Javascript
додано Автор Bergi, джерело
Майте на увазі, що використання оператора з виводить помилку в суворому режимі. Так що я б сказав, що може бути більше, ніж просто "захист" (але не можу сказати, що прямо зараз і специфікація не конкретна в цій точці).
додано Автор Felix Kling, джерело
Я вважаю, що головна небезпека у полягає в тому, що змінні піддаються всьому масштабу, але я бачив обхідні шляхи з IIFE. Очевидно, дуже повільно, коли ви можете просто кешувати пошук у змінній і використовувати це право? Але ця небезпека може бути перевагою.
додано Автор elclanrs, джерело
@Bergi Чим більше я читаю SO, тим більше я впевнений, що всі хороші питання вже задані.
додано Автор VisioN, джерело
@Bergi Чим більше я читаю SO, тим більше я впевнений, що всі хороші питання вже задані.
додано Автор VisioN, джерело
@Bergi Чим більше я читаю SO, тим більше я впевнений, що всі хороші питання вже задані.
додано Автор VisioN, джерело
eval використовує не-злое використанняS? Я можу подумати про те, що більше не застосовується: оцінювання рядків JSON, але завдяки JSON.parse нам не потрібно.
додано Автор Elias Van Ootegem, джерело
Головним аргументом проти використання з є відносна складність обґрунтування.
додано Автор finishingmove, джерело
Головним аргументом проти використання з є відносна складність обґрунтування.
додано Автор finishingmove, джерело
Головним аргументом проти використання з є відносна складність обґрунтування.
додано Автор finishingmove, джерело

7 Відповіді

Ключове слово з у Javascript - це трохи повернення до того, як він конкурував з VBScript наприкінці 90-х років. Це все ще існує, але вимкнено, якщо ви 'використовуєте строгий'; і вважаєте помилку майже кожним валідатором Javascript.

Існує дві основні проблеми, пов'язані з тим, як сфера роботи працює в Javascript:

var color = "green";
var foo = "bar";

with(elem.style) {
    color = "red";
    foo = "something else";
}

Тепер color ? Що таке foo ? Цей не тільки заплутаний код, але й тому, що Javascript шукає змінні в області з , це також дуже повільний код , оскільки тепер кожен оператор має додаткову область пошуку для кожного використовується змінна.

Це одна з причин, чому сучасні рамки, такі як jQuery і Prototype, використовують ланцюжки. Вони використовують функції call і apply для керування функціями, які представляє цей код , а це означає, що ви здійснюєте виклики this.something замість з (this) {something} .

Отже, щоб відповісти на ваше запитання: є одне хороше використання з у Javascript - що дозволяє веб-сайтам IE4 та IE5, написаним у 90-х роках, працювати сьогодні.

Це воно. Ви не повинні використовувати його в новому коді.

4
додано
Мені подобається, як ти думаєш. +1.
додано Автор VisioN, джерело

Єдине безпечне використання з взагалі не використовується. Немає завдання, яке без нього неможливо виконати, а сучасні стандарти відключити його в суворому режимі.

Для всіх цілей вважається дизайнерською помилкою, яка зберігається лише для зворотної сумісності.

1
додано
Як би ви виконали написання шаблону подібного без з та подібною простотою?
додано Автор Bergi, джерело
Так, я знаю, що, але зі змінною джерело шаблону потрібно використовувати точку accessors знову і знову. Якщо їх уникнути, ви можете скористатися з (і це добре).
додано Автор Bergi, джерело
@Bergi - Двигун шаблону Underscore не вимагає з . Знайдіть код і документи для settings.variable . Він використовує лише з , якщо ви не надаєте settings.variable .
додано Автор Michael Geary, джерело

Єдине безпечне використання з взагалі не використовується. Немає завдання, яке без нього неможливо виконати, а сучасні стандарти відключити його в суворому режимі.

Для всіх цілей вважається дизайнерською помилкою, яка зберігається лише для зворотної сумісності.

1
додано
Як би ви виконали написання шаблону подібного без з та подібною простотою?
додано Автор Bergi, джерело
Так, я знаю, що, але зі змінною джерело шаблону потрібно використовувати точку accessors знову і знову. Якщо їх уникнути, ви можете скористатися з (і це добре).
додано Автор Bergi, джерело
@Bergi - Двигун шаблону Underscore не вимагає з . Знайдіть код і документи для settings.variable . Він використовує лише з , якщо ви не надаєте settings.variable .
додано Автор Michael Geary, джерело

with simply puts the variable on top of the stack of "maps" searched for variables.

Звичайний стек (шукається зверху вниз)

  • вікно
  • (корінь - лише з вікном )

Так що якщо у вас є

var foo = { document: "doc.pdf" };
window.myFunc = function(){
    with( foo ){
        alert( document );
    }
}

Стек у межах with є

  • foo
  • вікно
  • (корінь - лише з вікном )

У ньому обов'язково буде надруковано foo.document , а не window.document .

У цьому випадку очевидно, що ви не повинні використовувати документ так, як це зазвичай використовується в браузерах. Але специфікація ECMAScript не визначає, що в інших середовищах інші змінні можуть бути в стеку за замовчуванням (навіть більше).

Небезпека полягає в тому, що все, що ви називаєте в операторі з , має те ж саме в стеку. Не вдалося виконати виклик document.url :

// Some 3rd-party library
function redirect( url ){
    document.url = url;   //url is undefined in document
}

var bar = { document: "20x20" };

with( bar ){
    redirect(); //
}
0
додано
Ні, це не корінь. Коренева область - це область, яка має вікно . Потім з'являється вікно . Див. вихідний код Firefox.
додано Автор Ondra Žižka, джерело
Це той самий випадок. І приклад з книги Давида Фланагана.
додано Автор Ondra Žižka, джерело
Не забувайте, що JavaScript не тільки в браузерах. Це також, наприклад, в Thunderbird, продуктах Adobe і т.д. А вікно не є основною змінною. Кореневий контекст містить інші об'єкти.
додано Автор Ondra Žižka, джерело
Не дуже, спробуйте window.window.window
додано Автор Ondra Žižka, джерело
Ха! Це не спрацювало багато років тому :) Ви отримали мене. Можливо, вони змінилися, щоб бути сумісними з IE, що зробили це.
додано Автор Ondra Žižka, джерело
Ну, вікно - це лише змінна в кореневій області, яка вказує на саму кореневу область, чи не так?
додано Автор Bergi, джерело
Саме так.
додано Автор Bergi, джерело
У чому різниця між кодом root і вікном ? І ваш приклад «небезпеки» є абсолютно неправильним; ви пробували?
додано Автор Bergi, джерело
Фактична небезпека описана тут: yuiblog.com/blog/ 2006/04/11/з-заявою-розглянуто-harmfu & zwnj; l
додано Автор Bergi, джерело
Якщо вікно є вашою кореневою областью, не розміщуйте їх на різних точках, щоб уникнути плутанини :-) . Перевірте код себе .
додано Автор Bergi, джерело

with simply puts the variable on top of the stack of "maps" searched for variables.

Звичайний стек (шукається зверху вниз)

  • вікно
  • (корінь - лише з вікном )

Так що якщо у вас є

var foo = { document: "doc.pdf" };
window.myFunc = function(){
    with( foo ){
        alert( document );
    }
}

Стек у межах with є

  • foo
  • вікно
  • (корінь - лише з вікном )

У ньому обов'язково буде надруковано foo.document , а не window.document .

У цьому випадку очевидно, що ви не повинні використовувати документ так, як це зазвичай використовується в браузерах. Але специфікація ECMAScript не визначає, що в інших середовищах інші змінні можуть бути в стеку за замовчуванням (навіть більше).

Небезпека полягає в тому, що все, що ви називаєте в операторі з , має те ж саме в стеку. Не вдалося виконати виклик document.url :

// Some 3rd-party library
function redirect( url ){
    document.url = url;   //url is undefined in document
}

var bar = { document: "20x20" };

with( bar ){
    redirect(); //
}
0
додано
Ні, це не корінь. Коренева область - це область, яка має вікно . Потім з'являється вікно . Див. вихідний код Firefox.
додано Автор Ondra Žižka, джерело
Не забувайте, що JavaScript не тільки в браузерах. Це також, наприклад, в Thunderbird, продуктах Adobe і т.д. А вікно не є основною змінною. Кореневий контекст містить інші об'єкти.
додано Автор Ondra Žižka, джерело
Це той самий випадок. І приклад з книги Давида Фланагана.
додано Автор Ondra Žižka, джерело
Не дуже, спробуйте window.window.window
додано Автор Ondra Žižka, джерело
Ха! Це не спрацювало багато років тому :) Ви отримали мене. Можливо, вони змінилися, щоб бути сумісними з IE, що зробили це.
додано Автор Ondra Žižka, джерело
Саме так.
додано Автор Bergi, джерело
Ну, вікно - це лише змінна в кореневій області, яка вказує на саму кореневу область, чи не так?
додано Автор Bergi, джерело
Якщо вікно є вашою кореневою областью, не розміщуйте їх на різних точках, щоб уникнути плутанини :-) . Перевірте код себе .
додано Автор Bergi, джерело
У чому різниця між кодом root і вікном ? І ваш приклад «небезпеки» є абсолютно неправильним; ви пробували?
додано Автор Bergi, джерело
Фактична небезпека описана тут: yuiblog.com/blog/ 2006/04/11/з-заявою-розглянуто-harmfu & zwnj; l
додано Автор Bergi, джерело

with simply puts the variable on top of the stack of "maps" searched for variables.

Звичайний стек (шукається зверху вниз)

  • вікно
  • (корінь - лише з вікном )

Так що якщо у вас є

var foo = { document: "doc.pdf" };
window.myFunc = function(){
    with( foo ){
        alert( document );
    }
}

Стек у межах with є

  • foo
  • вікно
  • (корінь - лише з вікном )

У ньому обов'язково буде надруковано foo.document , а не window.document .

У цьому випадку очевидно, що ви не повинні використовувати документ так, як це зазвичай використовується в браузерах. Але специфікація ECMAScript не визначає, що в інших середовищах інші змінні можуть бути в стеку за замовчуванням (навіть більше).

Небезпека полягає в тому, що все, що ви називаєте в операторі з , має те ж саме в стеку. Не вдалося виконати виклик document.url :

// Some 3rd-party library
function redirect( url ){
    document.url = url;   //url is undefined in document
}

var bar = { document: "20x20" };

with( bar ){
    redirect(); //
}
0
додано
Ні, це не корінь. Коренева область - це область, яка має вікно . Потім з'являється вікно . Див. вихідний код Firefox.
додано Автор Ondra Žižka, джерело
Не забувайте, що JavaScript не тільки в браузерах. Це також, наприклад, в Thunderbird, продуктах Adobe і т.д. А вікно не є основною змінною. Кореневий контекст містить інші об'єкти.
додано Автор Ondra Žižka, джерело
Це той самий випадок. І приклад з книги Давида Фланагана.
додано Автор Ondra Žižka, джерело
Не дуже, спробуйте window.window.window
додано Автор Ondra Žižka, джерело
Ха! Це не спрацювало багато років тому :) Ви отримали мене. Можливо, вони змінилися, щоб бути сумісними з IE, що зробили це.
додано Автор Ondra Žižka, джерело
Ну, вікно - це лише змінна в кореневій області, яка вказує на саму кореневу область, чи не так?
додано Автор Bergi, джерело
Саме так.
додано Автор Bergi, джерело
Якщо вікно є вашою кореневою областью, не розміщуйте їх на різних точках, щоб уникнути плутанини :-) . Перевірте код себе .
додано Автор Bergi, джерело
У чому різниця між кодом root і вікном ? І ваш приклад «небезпеки» є абсолютно неправильним; ви пробували?
додано Автор Bergi, джерело
Фактична небезпека описана тут: yuiblog.com/blog/ 2006/04/11/з-заявою-розглянуто-harmfu & zwnj; l
додано Автор Bergi, джерело

Оператор з - це лише скорочення для написання повторюваних звернень до об'єктів:

Для

foobar.foo.bar.baz = 'bubu';
foobar.foo.bar.buz = 'baba';

Ви можете написати

with(foobar.foo.bar){
    baz = 'bubu';
    buz = 'baba';
}

Thats nice! BUT will foobar.foo.bar be modified or will the global variables baz and buz modified? In some cases it is impossible to know Для sure.

JavaScript забезпечує кращу альтернативу

var better = foobar.foo.bar;
better.baz = 'bubu';
better.buz = 'baba';

Тепер немає ніякої двозначності.

0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram