JavaScript 구문 도메인 이해

JavaScript는 기존의 블록 레벨 도메인이 아니라 함수 도메인입니다!
1. 역할 영역
  • 자바스크립트 엔진은 코드가 실행되기 전에 이를 컴파일합니다. 이 과정에서 var a=2와 같은 성명은 두 가지 독립된 절차로 분해됩니다
  • 첫 번째 단계 (컴파일 단계): var a는 그 역할 영역에서 새로운 변수를 설명합니다.이것은 첫 번째 단계, 즉 코드 실행 전에 진행될 것이다.
    2단계(실행 단계): a = 2는 변수 a(LHS 조회)를 조회하고 값을 부여합니다.
  • LHS & RHS(현재 역할 영역 -> 상위 역할 영역 ->...-> 글로벌 역할 영역)
  • LHS(왼쪽): 변수를 찾으려는 컨테이너 자체
    RHS(오른쪽): 변수 값 찾기
    예:
    
    function foo(a){
    	var b = a;
    	return a + b;
    }
    var c = foo(2);
    // LHS(3 ):c;a( );b;
    // RHS(4 ):foo(2);=a;a;b;
  • 이상
  • 
    function foo(a){
    	console.log(a + b);
    	b = a;
    }
    foo(2);
    (1) ES5 엄격한 모드에서 LHS가 ReferenceError를 내보냅니다.엄격한 모드가 아닌 경우 LHS는 자동으로 글로벌 변수를 암시적으로 생성합니다.
    (2) 중첩된 모든 역할 영역에서 RHS 쿼리를 찾을 수 없으면 ReferenceError가 전송됩니다.
    (3) RHS에서 변수를 조회하지만 불합리한 조작을 시도하면 (null 또는 undefined 형식의 속성을 참조) TypeError를 던집니다.
    한마디로 요약하면 ReferenceError는 작용역 판별 실패와 관련이 있다.TypeError는 역할 영역 판별에 성공했지만 결과에 대한 조작이 불법적이거나 불합리하다는 것을 나타낸다.
    PS: 블로그에서 자바스크립트 함수와 프로토타입 함수 실행 덮어쓰기 등 문제를 원리적으로 논술하였습니다!!!
    2. 어법 작용역
    어법 작용역은 작용역이 코드를 쓸 때 함수 성명의 위치에 의해 결정된다는 것을 의미한다.JavaScript의 두 가지 메커니즘은 "사기"어법 작용 영역: eval(...)와 with.
  • eval
  • eval 함수는 문자열 매개 변수를 받아들일 수 있으며, 그 내용을 작성할 때 프로그램에 존재하는 것처럼 보일 수 있습니다. (현재 위치에서 코드를 생성하고 실행할 수 있습니다.)
    eval은 하나 이상의 성명을 포함하는'코드'문자열을 연산할 수 있으며, 이로써 이미 존재하는 어법 작용역 (운행 단계) 을 수정할 수 있습니다.
    
    function foo(str,a){
    	eval(str);
    	console.log(a, b);			//1 , 3
    	console.log(a, window.b);	//1 , 2
    }
    var b = 2;
    foo("var b = 3;", 1);
    설명: 상술한 전역 변수 b가 덮어썼습니다. b는 전역적이기 때문에 윈도우즈가 가능합니다.b 가져오기;그러나 비전역 변수가 덮어쓰면 접근할 수 없습니다!
    엄격한 모드:
    
    function foo(str,a){
    	"use strict";
    	eval(str);
    	console.log(a, b);			//1 , 2
    	console.log(a, window.b);	//1 , 2
    }
    var b = 2;
    foo("var b = 3;", 1);
  • with
  • with는 일반적으로 한 대상의 여러 속성을 반복적으로 인용하는 단축키로 여겨지며, 대상 자체를 반복해서 인용하지 않아도 된다.
    with는 대상의 속성을 역할 영역의 식별자로 처리하여 새로운 어법 역할 영역 (운행 단계) 을 만들었습니다.
    
    function foo(obj){
    	with(obj){
    		a = 2;
    	}
    }
    var o1 = { a : 3 };
    var o2 = { b : 3 };
    
    foo(o1);
    console.log( o1.a );	// 2
    
    foo(o2);
    console.log( o2.a );	// undefined
    console.log( a );		// 2, a !
    이 두 메커니즘의 부작용은 엔진이 컴파일할 때 역할 영역 검색을 최적화하지 못해 코드 운행 속도가 느려지는 것이다. 사용하지 않는 것을 권장한다!
    PS: 원리적으로 블로그 에서 with가 사용할 수 없는 원인을 논술하였습니다!!!
    3. 함수 작용역과 블록 작용역
    익명과 구명
    
    /*  ( arguments.callee ) */
    setTimeout(function(){
    	console.log("i wait 1 second!")
    },1000);
    /*  ( ) */
    setTimeout(function timeoutHandler(){
    	console.log("i wait 1 seco nd!")
    },1000);
    함수 표현식 즉시 실행
    
    /* IIFE  */
    var a = 2;
    (function IIFE(global){
    	var a = 3;
    	console.log(a);			//3
    	console.log(global.a);	//2
    })(window);
    /* UMD  */
    var b = 2;
    (function UMD(def){
    	def(window);
    })(function tmpF(global){
    	var b = 3;
    	console.log(b);			//3
    	console.log(global.b);	//2
    });
    블록 역할 영역
    try/catch는 블록 역할 영역을 만듭니다.
    
    try{
    	undefined();
    }catch(err){
    	console.log(err);	// 
    }
    console.log(err);	//ReferenceError: err is not defined
    
    /*  1 */
    for(var i=0;i<10;i++){}
    console.log(i);		//10
    /*  2 */
    {
    	console.log(bar);	//undefined  !!
    	var bar = 2;
    }
    ES6에 새로운 let 키워드 도입!!
    
    /*  1 */
    for(let i=0;i<10;i++){}
    console.log(i);		//SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    /*  2 */
    {
    	console.log(bar);	//SyntaxError  !!
    	let bar = 2;
    }
    ES6 코드를 ES6 호환 이전 환경으로 전환하는 두 가지 추천(대부분 ES5이지만 모두 그렇지 않음) 도구: Traceur와 let-er
    이상은 자바스크립트 어법 작용역에 대한 상세한 내용을 깊이 있게 이해하고 자바스크립트 어법 작용역에 대한 더 많은 자료는 저희 다른 관련 글을 주목해 주십시오!

    좋은 웹페이지 즐겨찾기