with
진술 에 대한 나의 대답에 대한 Alan Storm의 의견 은 저를 생각하게했습니다. 나는이 특정한 언어 기능을 사용해야 할 이유를 거의 찾지 못했고 그것이 어떻게 문제를 일으킬 수 있는지에 대해 많은 생각을하지 않았다. 이제 with
함정을 피하면서 어떻게 효과적으로 사용할 수 있는지 궁금 합니다.
이 with
진술 이 어디에 유용 했습니까?
with
되어 더 이상 그런 것이 없습니다.
with
진술 에 대한 나의 대답에 대한 Alan Storm의 의견 은 저를 생각하게했습니다. 나는이 특정한 언어 기능을 사용해야 할 이유를 거의 찾지 못했고 그것이 어떻게 문제를 일으킬 수 있는지에 대해 많은 생각을하지 않았다. 이제 with
함정을 피하면서 어떻게 효과적으로 사용할 수 있는지 궁금 합니다.
이 with
진술 이 어디에 유용 했습니까?
with
되어 더 이상 그런 것이 없습니다.
답변:
오늘 또 다른 용도가 생겨서 웹을 흥미롭게 검색하고 기존의 언급을 발견했습니다. 블록 범위 내 변수 정의 .
JavaScript는 C 및 C ++의 표면적 유사성에도 불구하고 변수를 정의 된 블록으로 범위를 지정하지 않습니다.
var name = "Joe";
if ( true )
{
var name = "Jack";
}
// name now contains "Jack"
루프에서 클로저 선언은 오류로 이어질 수있는 일반적인 작업입니다.
for (var i=0; i<3; ++i)
{
var num = i;
setTimeout(function() { alert(num); }, 10);
}
for 루프는 새로운 스코프를 도입하지 않기 때문에 num
값이 2
3 인 동일한 함수가 세 함수 모두에 의해 공유됩니다.
let
및with
의 도입 let
에 문 ES6 , 이러한 문제를 방지하기 위해 필요한 경우 새로운 범위를 소개 쉽게된다 :
// variables introduced in this statement
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
setTimeout(function() { alert(i); }, 10);
}
또는:
for (var i=0; i<3; ++i)
{
// variables introduced in this statement
// are scoped to the block containing it.
let num = i;
setTimeout(function() { alert(num); }, 10);
}
ES6을 보편적으로 사용할 수있을 때까지이 사용은 최신 브라우저 및 트랜스 파일러를 사용하려는 개발자로 제한됩니다. 그러나 다음을 사용하여이 동작을 쉽게 시뮬레이션 할 수 있습니다 with
.
for (var i=0; i<3; ++i)
{
// object members introduced in this statement
// are scoped to the block following it.
with ({num: i})
{
setTimeout(function() { alert(num); }, 10);
}
}
루프는 이제 의도 한대로 작동하여 0에서 2 사이의 값을 갖는 세 개의 개별 변수를 만듭니다 . 블록 내 에서 선언 된 변수는 C ++의 블록 동작과 달리 범위가 지정되지 않습니다 (C에서 변수는 시작시 선언되어야 함) 블록과 비슷합니다). 이 동작은 실제로 이전 버전의 Mozilla 브라우저에서 소개되었지만 다른 곳에서는 널리 채택되지 않은 let
블록 구문 과 매우 유사합니다 .
for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
. with 문의 범위 에서 toString () 은 Object 의 상속 된 속성 이므로 명시 적으로 정의 된 함수는 호출되지 않습니다. 그래도 여전히 좋은 대답입니다 :-)
with 문을 범위가 지정된 가져 오기의 간단한 형태로 사용하고 있습니다. 일종의 마크 업 빌더가 있다고 가정 해 봅시다. 쓰기보다는 :
markupbuilder.div(
markupbuilder.p('Hi! I am a paragraph!',
markupbuilder.span('I am a span inside a paragraph')
)
)
대신 쓸 수 있습니다 :
with(markupbuilder){
div(
p('Hi! I am a paragraph!',
span('I am a span inside a paragraph')
)
)
}
이 사용 사례의 경우 할당을 수행하지 않으므로 이와 관련된 모호성 문제가 없습니다.
context.bezierCurveTo
백 번 똑바로 사용 하는 경우 전화를 걸 때마다 말하고 var bc2 = context.bezierCurveTo;
갈 bc2(x,x,etc);
수 있습니다. 그것은 매우 빠르며 덜 장황한 반면, with
매우 느립니다.
이전의 의견에서 알 수 있듯이 with
주어진 상황에서 아무리 유혹을 느끼더라도 안전하게 사용할 수 있다고 생각하지 않습니다 . 이 문제는 여기서 직접 다루지 않으므로 반복하겠습니다. 다음 코드를 고려하십시오
user = {};
someFunctionThatDoesStuffToUser(user);
someOtherFunction(user);
with(user){
name = 'Bob';
age = 20;
}
이러한 함수 호출을주의 깊게 조사하지 않으면이 코드가 실행 된 후 프로그램의 상태를 알 수있는 방법이 없습니다. user.name
이미 설정되어 있으면 이제됩니다 Bob
. 이 설정되지 않은 경우, 세계는 name
초기화 또는 변경됩니다 Bob
및 user
개체가없이 유지됩니다 name
속성입니다.
버그가 발생합니다. 함께 사용 하면 하면 결국이 작업을 수행하고 프로그램이 실패 할 가능성을 높입니다. 더구나, 의도적으로 또는 작성자를 통해 with 블록에 전역을 설정하는 작업 코드가 발생할 수 있습니다. 그것은 스위치에서 쓰러지는 것과 매우 흡사합니다. 저자가 이것을 의도했는지 전혀 알지 못하며 코드를 "고정"하여 회귀를 일으킬 지 알 수 없습니다.
최신 프로그래밍 언어에는 기능이 가득합니다. 몇 년 동안 사용한 후 일부 기능은 불량한 것으로 밝혀져 피해야합니다. 자바 스크립트 with
도 그중 하나입니다.
나는 실제로 그 with
진술이 최근에 매우 유용하다는 것을 알았습니다 . 이 기술은 현재 프로젝트 (JavaScript로 작성된 명령 행 콘솔)를 시작할 때까지 실제로 발생하지 않았습니다. 특수 명령을 콘솔에 입력 할 수 있지만 전역 범위의 변수를 재정의하지 않는 Firebug / WebKit 콘솔 API를 에뮬레이션하려고했습니다. 나는 Shog9의 훌륭한 답변 에 대한 의견에서 언급 한 문제를 극복하려고 할 때 이것을 생각했습니다 .
이 효과를 달성하기 위해 전역 범위 뒤에있는 범위를 "계층화"하기 위해 두 개의 with 문을 사용했습니다.
with (consoleCommands) {
with (window) {
eval(expression);
}
}
이 기술의 가장 큰 장점은 성능상의 단점을 제외하고는 with
우리가 어쨌든 세계적인 범위에서 평가하고 있기 때문에 성명서에 대한 일반적인 두려움을 겪지 않는다는 것입니다. 수정되었습니다.
놀랍게도 다른 곳에서 사용 된 것과 동일한 기술인 Chromium 소스 코드 를 찾았을 때이 답변을 게시 할 수있었습니다 .
InjectedScript._evaluateOn = function(evalFunction, object, expression) {
InjectedScript._ensureCommandLineAPIInstalled();
// Surround the expression in with statements to inject our command line API so that
// the window object properties still take more precedent than our API functions.
expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
return evalFunction.call(object, expression);
}
편집 : 방금 Firebug 소스를 확인했으며 더 많은 레이어에 대해 4 개의 문을 묶었 습니다. 미친!
const evalScript = "with (__win__.__scope__.vars) { with (__win__.__scope__.api) { with (__win__.__scope__.userVars) { with (__win__) {" +
"try {" +
"__win__.__scope__.callback(eval(__win__.__scope__.expr));" +
"} catch (exc) {" +
"__win__.__scope__.callback(exc, true);" +
"}" +
"}}}}";
예, 그렇습니다 매우 합법적 인 사용이 있습니다. 손목 시계:
with (document.getElementById("blah").style) {
background = "black";
color = "blue";
border = "1px solid green";
}
기본적으로 다른 DOM 또는 CSS 후크는 환상적인 사용법입니다. "CloneNode"는 정의되지 않은 상태가 아니므로 사용자가 방해가되지 않고 가능한 한 글로벌 범위로 돌아갑니다.
Crockford의 속도 불만은 with에 의해 새로운 맥락이 만들어 졌다는 것입니다. 문맥은 일반적으로 비싸다. 동의한다. 그러나 방금 div를 만들었고 CSS를 설정하기위한 프레임 워크가없고 15 가지 정도의 CSS 속성을 직접 설정 해야하는 경우 컨텍스트를 만드는 것이 변수 생성 및 15 역 참조보다 저렴합니다.
var element = document.createElement("div"),
elementStyle = element.style;
elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";
기타...
with
. 그러나이 특별한 경우에는 다음과 같이 할 수 있습니다.element.style.cssText="background: black ; color: blue ; border: 1px solid green"
extend
jQuery 또는 Underscore.js 의 간단한 메소드를 사용하여 한 줄로 동일한 작업을 수행 할 수 $.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'})
있습니다.
.css()
방법을 사용하면 된다.
with
모호함없이 이점을 제공하기 위해 작은 도우미 함수를 정의 할 수 있습니다 .
var with_ = function (obj, func) { func (obj); };
with_ (object_name_here, function (_)
{
_.a = "foo";
_.b = "bar";
});
with_
더러워진 두 배 버전 (function(_){ _.a="foo"; })(object_here);
(c / java 스타일 블록을 시뮬레이션하는 표준 방법)으로 인해 더 많은 버그 가 발생합니다 . 대신 사용하십시오.
다음을 수행 할 수 있으므로 그만한 가치가없는 것 같습니다.
var o = incrediblyLongObjectNameThatNoOneWouldUse;
o.name = "Bob";
o.age = "50";
with
.
나는 함께 사용하지 않으며, 이유를 보지 않으며, 권장하지 않습니다.
문제 는 ECMAScript 구현이 수행 할 수있는 수많은 어휘 최적화를 방지with
한다는 것 입니다. 빠른 JIT 기반 엔진의 등장으로이 문제는 가까운 시일 내에 더욱 중요해질 것입니다.
것처럼 보일 수 있습니다 with
(말하자면, 대신 공통 익명 함수 래퍼의 새로운 범위를 도입하거나 앨리어싱 자세한 교체 할 때), 그러나 그것의 청소기 구조를 허용 정말 그럴 가치가 없어 . 성능 저하 외에도 항상 잘못된 개체의 속성 (사출 된 범위의 개체에서 속성을 찾을 수없는 경우)에 할당하고 전역 변수를 잘못 도입 할 위험이 있습니다. IIRC, 후자의 문제는 Crockford가 피하도록 권장 한 것 with
입니다.
with(){}
다른 답변, 현대 브라우저에서 제공되는 것과 같은 구조 비용에 어려운 숫자가있는 경우 보고 싶습니다. 그들!
with(){}
: 새로운 범위를 설정하는 것은 with
테스트 한 모든 브라우저에서 매우 비쌉니다. 매우 자주 호출되는 코드에서는 이것을 피하고 싶을 것입니다. 또한 Chrome은 with()
범위 내에서 실행되는 모든 코드에 큰 타격을 입었습니다 . 흥미롭게도 IE는 with()
블록 내 코드에 대해 최고의 성능 특성을 가졌 습니다. 설정 비용을 고려하지 않고 with()
IE6 및 IE8 VM에서 가장 빠른 구성원 액세스 수단을 제공합니다 (이 VM은 전체적으로 가장 느리지 만). 좋은 물건, 감사합니다 ...
with()
는 Chrome에서 거의 10 배 느리고 IE에서는 두 배 이상 빠릅니다 ...!
Visual Basic.NET도 비슷한 With
문장을 가지고 있습니다. 내가 사용하는 가장 일반적인 방법 중 하나는 여러 속성을 빠르게 설정하는 것입니다. 대신에:
someObject.Foo = ''
someObject.Bar = ''
someObject.Baz = ''
, 난 쓸수있다:
With someObject
.Foo = ''
.Bar = ''
.Baz = ''
End With
이것은 단지 게으름의 문제가 아닙니다. 또한 훨씬 더 읽기 쉬운 코드를 만듭니다. 그리고 JavaScript와 달리 명령문의 영향을받는 모든 부분 앞에 .
(점) 을 붙여야하기 때문에 모호성이 없습니다 . 따라서 다음 두 가지는 명확하게 구분됩니다.
With someObject
.Foo = ''
End With
vs.
With someObject
Foo = ''
End With
전자는 someObject.Foo
; 후자는 외부Foo
범위에 있습니다 someObject
.
JavaScript의 구분이 없기 때문에 모호성의 위험이 너무 높기 때문에 Visual Basic의 변형보다 훨씬 유용하지 않습니다. 그 외에는 with
여전히 가독성을 향상시킬 수있는 강력한 아이디어입니다.
with
이 작업을 수행하는 것처럼 객체의 내용을 블록에 로컬 변수로 도입하는 데 사용할 수 있습니다 작은 템플릿 엔진 .
"with"를 사용하면 코드를 더 건조하게 만들 수 있습니다.
다음 코드를 고려하십시오.
var photo = document.getElementById('photo');
photo.style.position = 'absolute';
photo.style.left = '10px';
photo.style.top = '10px';
다음과 같이 건조시킬 수 있습니다.
with(document.getElementById('photo').style) {
position = 'absolute';
left = '10px';
top = '10px';
}
나는 당신이 가독성이나 표현력을 선호하는지 여부에 달려 있다고 생각합니다.
첫 번째 예제는 더 읽기 쉽고 대부분의 코드에 권장됩니다. 그러나 대부분의 코드는 어쨌든 꽤 길들입니다. 두 번째는 조금 더 모호하지만 코드의 크기와 불필요한 변수를 줄이기 위해 언어의 표현적인 특성을 사용합니다.
Java 또는 C #을 좋아하는 사람들이 첫 번째 방법 (object.member)을 선택하고 Ruby 또는 Python을 선호하는 사람들이 후자를 선택한다고 생각합니다.
나는 명백한 사용이 지름길이라고 생각합니다. 예를 들어 객체를 초기화하는 경우 많은 "ObjectName"을 입력하면됩니다. lisp의 "with-slots"처럼 쓸 수있는 종류
(with-slots (foo bar) objectname
"some code that accesses foo and bar"
글쓰기와 같습니다
"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""
언어가 "Objectname.foo"를 허용하지만 여전히 그래도 이것이 왜 지름길인지 더 분명합니다.
with-slots
사용중인 슬롯을 지정해야하지만 with
런타임에 바인딩되는 슬롯을 사용합니다.
델파이와 경험을 갖는 것은, 그 사용 말할 것 과를 것이 최후의 리 소드 크기 최적화이어야하며 안전성을 확인하기 위해 정적 코드 분석에 액세스 할 수있는 일종의 자바 스크립트 최소화 알고리즘에 의해 수행 될 수 있습니다.
with 문 을 자유로이 사용하여 얻을 수있는 범위 지정 문제 는 a **에 큰 고통이 될 수 있으며 누구도 디버깅 세션을 경험하여 코드에서 무슨 일이 일어나고 있는지 파악하고 싶지는 않습니다. 전역 또는 외부 범위 변수 대신 객체 멤버 또는 잘못된 로컬 변수를 캡처 한 경우에만 찾을 수 있습니다.
VB with statement는 범위를 명확하게하기 위해 점이 필요하다는 점에서 더 좋습니다. 그러나 Delphi with statement는 헤어 트리거가있는로드 된 총이며, 자바 스크립트 하나가 동일한 경고를 보장 할만 큼 충분히 비슷한 것처럼 보입니다.
with를 사용하는 것은 권장되지 않으며 ECMAScript 5 엄격 모드에서는 금지되어 있습니다. 권장되는 대안은 속성을 액세스하려는 객체를 임시 변수에 할당하는 것입니다.
with 문을 사용하여 코드 크기를 줄이거 나 개인 클래스 멤버에 사용할 수 있습니다 (예 :
// demo class framework
var Class= function(name, o) {
var c=function(){};
if( o.hasOwnProperty("constructor") ) {
c= o.constructor;
}
delete o["constructor"];
delete o["prototype"];
c.prototype= {};
for( var k in o ) c.prototype[k]= o[k];
c.scope= Class.scope;
c.scope.Class= c;
c.Name= name;
return c;
}
Class.newScope= function() {
Class.scope= {};
Class.scope.Scope= Class.scope;
return Class.scope;
}
// create a new class
with( Class.newScope() ) {
window.Foo= Class("Foo",{
test: function() {
alert( Class.Name );
}
});
}
(new Foo()).test();
with 문은 범위를 수정하려는 경우 런타임에 조작 할 수있는 고유 한 글로벌 범위를 갖는 데 필요한 것입니다. "toUpper", "toLower"또는 "isNumber", "clipNumber"aso와 같이 자주 사용되는 특정 도우미 함수에 상수를 넣을 수 있습니다.
나쁜 성능에 대해 자주 읽습니다. 함수를 범위 지정해도 성능에 영향을 미치지 않습니다. 실제로 FF에서는 범위가 지정된 함수가 범위가없는 것보다 빠르게 실행됩니다.
var o={x: 5},r, fnRAW= function(a,b){ return a*b; }, fnScoped, s, e, i;
with( o ) {
fnScoped= function(a,b){ return a*b; };
}
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnRAW(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnScoped(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
따라서 위에서 언급 한 방식으로 with 문은 성능에 부정적인 영향을 미치지 않지만 코드 크기를 줄이면 모바일 장치의 메모리 사용에 영향을 미치는 좋은 방법입니다.
with를 사용하면 많은 구현에서 코드가 더 느려집니다. 이제 모든 것이 조회를 위해 추가 범위로 래핑되기 때문입니다. JavaScript에서 with를 사용할 정당한 이유는 없습니다.
var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;
에 평균 2500을 var obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;
제공하고 평균 750 을 제공하여 3 배 이상 느린 속도를 사용합니다.
with
코드에 대해 1138 이고 그렇지 않은 경우 903이었습니다. 타이트한 루프에서도 이러한 작은 차이로 성능에 대해 걱정하기 전에 코딩 단순성과 사례별로 리팩토링의 용이성을 기반으로 선택합니다.
클로저를 사용하는 드롭 인 대체와 같이 객체 리터럴 사용이 흥미 롭습니다.
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
(function(info)
{
nodes[i].onclick = function(){ showStuff(info) };
})(data[i]);
}
또는 with 문과 유사한 문
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
with({info: data[i]})
{
nodes[i].onclick = function(){ showStuff(info) };
}
}
실제 위험은 with 문의 일부가 아닌 변수를 실수로 최소화하는 것이라고 생각합니다. 그래서 객체 리터럴이 전달되는 것을 좋아하는 이유는 코드의 추가 컨텍스트에서 무엇이 될지 정확하게 볼 수 있습니다.
나는 with
진술 과 함께이 모호성을 제거하는 "병합"기능을 만들었다 :
if (typeof Object.merge !== 'function') {
Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
for(var i in o2) { o1[i] = o2[i]; }
return o1;
};
}
와 비슷하게 사용할 수 with
있지만 영향을 미치지 않는 범위에는 영향을 미치지 않습니다.
용법:
var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
function NewObj() {
Object.merge(this, {size: 4096, initDate: new Date()});
}
몇 가지 간단한 코드 조각을 위해, 나는 같은 삼각 함수 사용하고자하는 sin
, cos
정도 모드에서 대신 복사 모드 등. 이를 위해 AngularDegree
객체를 사용 합니다.
AngularDegree = new function() {
this.CONV = Math.PI / 180;
this.sin = function(x) { return Math.sin( x * this.CONV ) };
this.cos = function(x) { return Math.cos( x * this.CONV ) };
this.tan = function(x) { return Math.tan( x * this.CONV ) };
this.asin = function(x) { return Math.asin( x ) / this.CONV };
this.acos = function(x) { return Math.acos( x ) / this.CONV };
this.atan = function(x) { return Math.atan( x ) / this.CONV };
this.atan2 = function(x,y) { return Math.atan2(x,y) / this.CONV };
};
그런 다음 with
블록 에서 추가 언어 노이즈없이 삼각 모드에서 삼각 함수를 사용할 수 있습니다 .
function getAzimut(pol,pos) {
...
var d = pos.lon - pol.lon;
with(AngularDegree) {
var z = atan2( sin(d), cos(pol.lat)*tan(pos.lat) - sin(pol.lat)*cos(d) );
return z;
}
}
즉, 객체를 함수 모음으로 사용하여 제한된 코드 영역에서 직접 액세스 할 수 있습니다. 나는 이것이 유용하다고 생각한다.
with
이 방법으로 문장 을 사용하는 것은 좋은 생각 이 아닙니다. 어떤 함수가 전역이고 어떤 함수가 객체 범위에서 호출되는지 알 수 없기 때문에 코드를 읽기가 어렵습니다. 객체 범위는 전역 네임 스페이스에서 액세스하려고 시도합니다
z = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;
동일한 결과를 줄 것이지만 그것은 공포입니다.
with
있다고 확신합니다.
유용성이 with
코드 작성 방법에 달려 있다고 생각합니다 . 예를 들어 다음과 같은 코드를 작성하는 경우 :
var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();
그런 다음 with
이를 수행하여 코드의 가독성을 향상시킬 것이라고 주장 할 수 있습니다 .
var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
sHeader = header.toString();
sContent = content.toString();
sFooter = content.toString();
}
반대로, 당신이 데메테르 법칙을 위반하고 있다고 주장 할 수 있지만, 다시는 그렇지 않을 수도 있습니다. 나는 digress =).
무엇보다도 Douglas Crockford는 을 사용 하지 않는 것이 좋습니다 with
. 난 당신에 대한 자신의 블로그 게시물을 체크 아웃 할 것을 촉구 with
하고 대안을 여기에 .
W3schools http://www.w3schools.com/js/js_form_validation.asp 에서 자바 스크립트로 양식의 유효성을 확인해야합니다 . 여기서 "양식"이라는 이름의 입력을 찾기 위해 오브젝트 양식이 "스캔"됩니다.
그러나 양식의 필드 이름이나 수량에 관계없이 모든 필드가 비어 있지 않은 것으로 확인되도록 모든 형식에서 가져 오도록 수정했습니다. 글쎄, 나는 텍스트 필드 만 테스트했습니다.
그러나 with ()는 일을 더 단순하게 만들었습니다. 코드는 다음과 같습니다.
function validate_required(field)
{
with (field)
{
if (value==null||value=="")
{
alert('All fields are mandtory');return false;
}
else
{
return true;
}
}
}
function validate_form(thisform)
{
with (thisform)
{
for(fiie in elements){
if (validate_required(elements[fiie])==false){
elements[fiie].focus();
elements[fiie].style.border='1px solid red';
return false;
} else {elements[fiie].style.border='1px solid #7F9DB9';}
}
}
return false;
}
다음 with
은 객체에 저장된 값을 기반으로 객체 리터럴에 새 요소를 추가 하는 데 유용합니다 . 오늘 방금 사용한 예는 다음과 같습니다.
사용할 수있는 가능한 타일 세트 (위쪽, 아래쪽, 왼쪽 또는 오른쪽을 향한 개구부)가 있었고 게임 시작시 항상 배치되고 잠길 타일 목록을 추가하는 빠른 방법을 원했습니다. . types.tbr
목록의 각 유형에 대해 입력을 계속하고 싶지 않으므로 방금 사용했습니다 with
.
Tile.types = (function(t,l,b,r) {
function j(a) { return a.join(' '); }
// all possible types
var types = {
br: j( [b,r]),
lbr: j([l,b,r]),
lb: j([l,b] ),
tbr: j([t,b,r]),
tbl: j([t,b,l]),
tlr: j([t,l,r]),
tr: j([t,r] ),
tl: j([t,l] ),
locked: []
};
// store starting (base/locked) tiles in types.locked
with( types ) { locked = [
br, lbr, lbr, lb,
tbr, tbr, lbr, tbl,
tbr, tlr, tbl, tbl,
tr, tlr, tlr, tl
] }
return types;
})("top","left","bottom","right");
require.js를 사용할 때 명시 적으로 arity를 관리하지 않아도하기 위해 with를 사용할 수 있습니다.
var modules = requirejs.declare([{
'App' : 'app/app'
}]);
require(modules.paths(), function() { with (modules.resolve(arguments)) {
App.run();
}});
requirejs.declare의 구현 :
requirejs.declare = function(dependencyPairs) {
var pair;
var dependencyKeys = [];
var dependencyValues = [];
for (var i=0, n=dependencyPairs.length; i<n; i++) {
pair = dependencyPairs[i];
for (var key in dependencyPairs[i]) {
dependencyKeys.push(key);
dependencyValues.push(pair[key]);
break;
}
};
return {
paths : function() {
return dependencyValues;
},
resolve : function(args) {
var modules = {};
for (var i=0, n=args.length; i<n; i++) {
modules[dependencyKeys[i]] = args[i];
}
return modules;
}
}
}
Andy E가 Shog9의 답변에 대한 의견에서 지적 했듯이이 잠재적으로 예기치 않은 동작 with
은 객체 리터럴과 함께 사용할 때 발생합니다 .
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with ({num: i}) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "[object Object]"
}
}
그 예기치 않은 행동은 이미 의 특징 이 아니었다with
.
이 기술을 실제로 사용하려면 최소한 프로토 타입이 null 인 객체를 사용하십시오.
function scope(o) {
var ret = Object.create(null);
if (typeof o !== 'object') return ret;
Object.keys(o).forEach(function (key) {
ret[key] = o[key];
});
return ret;
}
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with (scope({num: i})) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "a"
}
}
그러나 이것은 ES5 +에서만 작동합니다. 또한 사용하지 마십시오 with
.
사용자가 응용 프로그램의 일부 동작을 수정하기 위해 코드를 업로드 할 수있는 프로젝트를 진행 중입니다. 이 시나리오에서는 with
코드를 사용하여 엉망으로 만드는 범위 밖의 항목을 수정하지 않도록 절을 사용했습니다 . 이 작업을 수행하는 데 사용하는 코드의 단순화 된 부분은 다음과 같습니다.
// this code is only executed once
var localScope = {
build: undefined,
// this is where all of the values I want to hide go; the list is rather long
window: undefined,
console: undefined,
...
};
with(localScope) {
build = function(userCode) {
eval('var builtFunction = function(options) {' + userCode + '}');
return builtFunction;
}
}
var build = localScope.build;
delete localScope.build;
// this is how I use the build method
var userCode = 'return "Hello, World!";';
var userFunction = build(userCode);
이 코드는 사용자 정의 코드가 다음과 같은 전역 범위의 객체에 액세스 할 수 없도록합니다. window
가 클로저를 통해 변수 나 로컬 변수에 .
현명한 한마디로, 사용자가 제출 한 코드에 대해 정적 코드 검사를 수행하여 다른 범위를 사용하여 전역 범위에 액세스하지 않는지 확인해야합니다. 예를 들어 다음 사용자 정의 코드는 다음에 대한 직접 액세스 권한을 갖습니다 window
.
test = function() {
return this.window
};
return test();
나의
switch(e.type) {
case gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED: blah
case gapi.drive.realtime.ErrorType.CLIENT_ERROR: blah
case gapi.drive.realtime.ErrorType.NOT_FOUND: blah
}
~로 비등하다
with(gapi.drive.realtime.ErrorType) {switch(e.type) {
case TOKEN_REFRESH_REQUIRED: blah
case CLIENT_ERROR: blah
case NOT_FOUND: blah
}}
품질이 낮은 코드를 믿을 수 있습니까? 아니요, 우리는 그것이 완전히 읽을 수 없도록 만들어졌습니다. 이 예제는 내가 가독성을 올바르게 가지고 있다면 with-statement가 필요 없다는 것을 명백히 증명합니다.)