js enhance the scope and variables

JS Scope

Scope (stack memory, the execution context)

Global scope (global stack memory)
	浏览器打开一个页面,开始运行时率先形成一个栈内存,这个栈内存又叫全局作用域,为代码提供执行环境,在全局作用域下会生成一个全局的大对象叫window。
	浏览器打开,生成的全局作用域一般不销毁,直到页面关闭。
console.log(window.Number)` 
Global Variables
在全局作用域下声明的变量就是全局变量
	全局变量的区别
	用var和function 声明的变量会在全局作用域下率先创建,而且也会给window增加属性,属性名是变量名,属性值是变量名储存的值(let不可以)
var s = 12;
function fn(){}
console.log(window.s)
console.log(window.fn)
let a = 12;
console.log(window.a) // undefined`
varfunction可以重复创建同一个变量名(let不可以)
var a = 12;
var a = 13;
console.log(a) // 13
let a = 12; // 报错  SyntaxError(语法错误)
let a = 13;` 
varfunction有变量提升(let没有)
b = 12 // 等价于window.b = 12因为window.可以省略
var b = 12(有变量提升)
var a,b,c = 12; //undefined   undefined  12
//创建变量a,b,c,但是只给c赋值
var a = 12,b = 13, c = 14; // 创建三个变量,给每一个变量都进行赋值
var a = b = c = 12; // 等价于 var a = 12; b = 12; c = 12;
Private scope (private stack memory)
	全局作用域生成之后才会有私有作用域,私有作用域属于全局作用域
		函数执行时会形成一个私有作用域(私有栈内存)为函数内的代码执行提供环境。
	
	创建函数时
			首先开辟一个堆内存生成一个16进制的空间地址
			把函数体里的代码以字符串的格式存储进去
			把16进制的地址赋值给函数名
	执行函数时
		首先开辟出一个私有栈内存(私有作用域)
		形参赋值
		变量提升
		代码从上往下执行
		作用域是否被销毁
Private variables
	在私有作用域中定义的变量就是私有变量(var、function、let、const····)
			形参也是私有变量
	在私有作用域里使用一个变量,如果自己私有作用域里有,直接用自己的,如果没有,就取上一级作用域的
			函数外边不能拿到函数里边的变量
var a = 12;
function fn(a) {
        console.log(a) //13
    }
    fn(13)
    var name = 'erYa';
    function fn(name){
        function name(){
        }
        name = 7;
        console.log(name)
    }
    fn(name)
    let y = 12;
    function fn(){
        function y(){}
        y =100;
        console.log(y) // 100
    }
    fn();
    console.log(y) // 12
    var num = 12;
    function fn(){
        var num = 0
        num++
    }
    fn();
    console.log(num)
Scope lookup function
		函数的上一级作用域是谁,在函数定义的时候就已经确定了,函数在哪创建的,他的上一级作用域就是谁,跟函数在哪执行没有关系。
Scope chain lookup mechanism
		在私有作用域中,函数执行,如果要使用一个变量,自己作用域要是有,就使用自己的,要是没有,就向上一级作用域查找,上一级还没有,在向上一级查找,直到找到全局作用域,如果还没有就报错--->这种一级一级向上查找的机制就是【作用域链查找机制】

Variable mention sound (L)

	浏览器解析代码的一个过程
		变量提升的含义
				在当前作用域,代码执行之前。浏览器会对当前作用域里的带var和function进行提前声明和定义。
				带var的会只声明(创建变量),不定义(赋值)
		
				带function的既声明(创建变量),又定义(赋值)
Variable lift mechanism
		当浏览器开辟出供代码执行的栈内存之后,代码并没有自上而下立即执行,而是继续做了一些事情:把当前作用域中所有带var/function关键字的进行提前的声明和定义
console.log(a) // undefind
var a =12; // a =12	
console.log(a) // 12
/*  console.log(num);
 var num = 100;
 console.log(num); */
 console.log(window.a); // undefined
 console.log(b); // 报错 引用错误 在当前代码之后的代码不在运行
 var a = 10;
 b = 12;
/* 
console.log(b; // 报错 语法错误,他会使整个页面不运行
        
*/
console.log(a); // undefined
console.log(b); // 引用错误
var a = b = c = 100;
console.log(a); // undefined
console.log(b); // undefined
console.log(c); // undefined
var a,b,c = 100;
console.log(a);// undefined
console.log(b);// undefined
console.log(c);// 100
function fn(){
   console.log(num);
   var num = 12;
}
fn();
console.log(num)
/* 
变量提升
var name
fn (){}
*/
var name = 'jinYu';
function fn(name){
    /* 
    name // f
    */
    console.log(name); //f
    function name(){}
    console.log(name); // f
}
fn(name)
/* 


Special case of variable lift

Variable lift occurs on the left side of the equal sign
var a = function () {}//此处,浏览器变量提升时,只识别var,不识别function
No matter if the condition is satisfied, if the code in the variable should be carried out to enhance the
console.log(num)//undefined
if(false){
  var num = 12;
}
console.log(num)//undefined
console.log(fn); // undefined
    // 在老版本浏览器里,if条件里的function既声明又定义,
    // 在新版本浏览器里,if条件里的函数只声明不定义
if(false){
     // 条件一旦成立,第一件事就是给函数名赋值,然后在执行代码
     fn()
     function fn(){}
 }
 console.log(fn) // undefined
console.log(fn); // undefined
    // 在老版本浏览器里,if条件里的function既声明又定义,
    // 在新版本浏览器里,if条件里的函数只声明不定义
if(true){
     // 条件一旦成立,第一件事就是给函数名赋值,然后在执行代码
     fn()
     function fn(){}
 }
 console.log(fn) // fn(){}
In the function, although return the following code is not executed, but to be variable lift
function fn() {
     console.log(ss); // undefined
     return;//中断后边代码执行
     var ss = 34;//此处的ss仍然要变量提升。永远是undefined
 }
 fn()
Anonymous function without variable lift
(function(){
            
})()

and let var differences:

		1.let和const不存在变量提升机制,var和function有变量提升
          		创建变量六种方式中:var和function有变量提升,而let,const,class,import不存在这个机制 
        2.var允许重复声明,而let不允许
            在相同作用域中或执行上下文中,使用var和function声明变量并且重复声明,是不会有影响的(声明第一次后,在遇到就不再重复声明)
            但是let和const不行,浏览器会校验当前作用域中是否存在这个变量,已存在,则再次基于let等重新声明就会报错 
       3.let能解决typeof检测出现的暂时性死区问题(let比var更严谨)
           	  console.log(a);//报错   a is not defined
            	console.log(typeof a);//undefined  本该报错 ,bug浏览器死区
            解决方法;
          	  console.log(typeof a);
           	 let a; 作用域与变量提升

JS error in

	SyntaxError(语法错误) 会使整个页面不运行 
	引用错误ReferenceError 在当前代码之后的代码不运行
	
	引用错误
			他会使,报错的代码 之后的代码不运行
	语法错误
			他会使页面不运行

Examples of variable lift

//  1.    
         var i = 5;
        function fn(i) {
            return function (n) {
                console.log(n + (++i));//4,8,12,10,5
            }
        }
        var f = fn(1);
        f(2);
        fn(3)(4);
        fn(5)(6);
        f(7);
        console.log(i);
    // let f = function(n){
    //     console.log(n+(++1))
    // }
    // let f(2) = function(2){
    //     console.log(2+(++1))//4
    // }
    // function (n){
    //     console.log(n+(++3))
    // }(4)
    // function(4){
    //     console.log(4(++3))//8
    // }
    // function (n){
    //     console.log(n+(++5))
    // }(6)
    // function (6){
    //     console.log(6+(++5))//12
    // }
    // let f(7) = function(7){
    //     console.log(7+(++2))//10 //上面为2 所以 ++2
    // }
// 2.
    var ary = [12, 23];
    function fn(ary) {
    console.log(ary);//[12,23]
    ary[0] = 100;   //[100,23]
    ary = [100];    // [100]  //新创建私有作用域
    ary[0] = 0;     //[0]
    console.log(ary);//[0]
    }
    fn(ary);
    console.log(ary);//[100,23]连接全局作用域下面
// 3.
    console.log(a)  //undefined
    if(!('a' in window)){   //false  取反为false
        var a = 13
    }
    console.log(a) //undefined
//4.
    var s = 5;
    function fn() {
        var n = 0;
        function f() {
            n++;
            console.log(n); // 1   //2
        }
        f();
        return f;
    }
    var r = fn();
    r();
    console.log(s); //5
//5.
    var a = 4;
    var f = 3;
    function b(x,y,a) {  // x,y,a = 1,2,f   a = f =3
        alert(a);        //a=3
        // 形参和arguments存在映射关系;
        arguments[2]=10;  //1,2,10
        alert(a);          //a=10
    }
    a=b(1,2,f);
    alert(a);   //undefined        //a = b(1,2,10) //b这个函数没有return  所以undefined
    console.log(f);//3
//6.
    var foo='hello';
    (function(foo){
        console.log(foo); //hello
        var foo=foo||'world';  //如果前面转布尔为false,取后面的值 ,反之取前面的值    'hello'字符串转布尔为true
        console.log(foo); //hello
    })(foo);
    console.log(foo); //hello
//7.
f = function(){return true}//true
g = function(){return false}//false
~function(){
    if(g() && [] == ![]){
        f = function(){return false}
         function g(){return true} 
    }
}();
console.log(f()) //true
console.log(g()) //false
Published 17 original articles · won praise 23 · views 374

Guess you like

Origin blog.csdn.net/wang_js_amateyr/article/details/103414547