javascript 变量声明 和 作用域

变量的声明

  1.变量声明具有提升机制,Javascript在执行时,会把所有的声明都提升到当前作用域前面。

  先看一下下面的例子:

(function(){
  alert(b)//b is not defined
  alert(a); //undefined
  var a = 200;
})()

  运行的结果分别是:b is not defined ; undefined

  分析: 变量a的声明被提前,所以最初代码相当于:

(function(){
  var a;//声明变量a
  alert(b)//b is not defined
  alert(a); //undefined
  a = 200; //(定义并)初始化变量a
})()

  b不用解释,因为找不到b,所以会报错。a是应为声明被提前了,所以可以找到a,但变量a并没有赋值,所以会输出undefined.

作用域:(全局作用域、函数作用域、eval作用域、ES6块级作用域)

  1.  函数体内部,局部变量的优先级比同名的全局变量优先级高。

var a = 100;
(function(){
    alert(a)//undefined
    var a = 200;
    alert(a)//200
})()

  运行上面的例子可以输出: undefined;200。

  分析:第一个alert为什么会是undefined呢?这里有变量的两个知识点:第一个是变量声明会提前,第二个就是局部变量的优先级比同名全局变量优先级高。上面的代码相当于:

var a = 100;
(function(){
    var a;
    alert(a)//undefined
    a = 200;
    alert(a)//200
})()

在函数作用域内,变量a的声明被提前了,函数外全局变量a被函数内变量a覆盖。所以会输出undefined;第二个输出200是因为a=200被赋值的原因。

  2. ECMA2015 没有块级作用域,只有函数作用域和全局作用域 (ECMA2016 引入块级作用域)

var a = 100;
if(true){
    alert(a);//100
    var a = 200;
    alert(a);//100
}

   上面代码输出结果为:100,200。说明javascript是没有块级作用域的。javasctipt中唯一拥有作用域的结构的是函数function

 

综上:下面的代码的输出结果就好理解了

var a = 100;
var b = 200;
function test(){
    alert(a); //undefined
    alert(b); //200
    b = 300;
    alert(b); //300
    var a = 1;
    alert(a); //1
}
test();

 自由变量:一个变量在当前作用域中没有定义,但被使用了,这种变量就叫做自由变量

  自由变量的取值怎么查找:在函数定义的地方向上级作用域一层一层依次查找,直到找到为止,如果在全局作用域下都没有查找到,就包错xxx is not undefined

  注意: 自由变量的查找是在函数定义的地方查找,而不是在执行的地方

闭包:作用域应用的特殊情况

  闭包有两种表现形式:1.函数作为返回值2.函数作为参数

  例子:函数作为返回值

          function create(){
                const a = 100;
                return function(){
                    console.log(a); // 此处是函数定义的地方,所以变量a 的值,应该是在此处向上级作用域查找,即100
                }
            }
            const fn1 = create()
            const a = 200;
            fn1() //100

  例子2:函数作为参数

           function print(fn){
                const b = 100
                fn()
            }
            const b = 200
            function fn(){
                console.log(b)  //b 定义的地方,查找b的值应该在此处向上级作用域查找,所以最后输出的事200,而不是100
            }
            print(fn) // 200

 this 的不同场景,如何取值?

  this的指向是在函数执行的时候判断的,而不是在定义的时候(这个和作用域中自由变量的取值刚好相反)

this 的几种赋值场景情况:

1、做为普通函数  

           function fn(){
                console.log(this)
            }
            fn() //window

2、使用 call apply bind 调用

           function fn(){
                console.log(this)
            }
            fn() //window
            fn.call({x:100}) // {x:100}
            fn.apply ({x:200}) // {x:200}
            const fn3 = fn.bind({x:300})
            fn3() //{x:300}

3、做为对象方法被调用

              const zhangsan = {
                name:'张三',
                sayHi(){
                    //this 等于当前对象
                    console.log(this)
                },
                wait(){
                    setTimeout(function(){
                        //this 等于 window
                        console.log(this)
                    })
                }
               
            }
            zhangsan.sayHi() //zhangsan对象
            zhangsan.wait() //Window
           

4、在箭头函数中调用

            const zhangsan = {
                name:'张三',
                sayHi(){
                    //this 等于当前对象
                    console.log(this)
                },
                wait(){
                    setTimeout(function(){
                        //this 等于 window
                        console.log(this)
                    })
                },
                waitAgain(){
                    //this 等于 当前对象
                    setTimeout(()=>{
                        //箭头函数this的取值,取上级作用域的值
                        //即 this 等于 当前对象
                        console.log(this)
                    })
                }
            }
            zhangsan.sayHi() //zhangsan对象
            zhangsan.wait() //Window
            zhangsan.waitAgain()//zhangsan对象

5、在class 方法中调用

           class People{
                constructor(name,age){
                    //this 指向实例对象
                    this.name = name
                    this.age = age
                }
                sayHi(){
                    //this 指向实例对象
                    console.log(this)
                }
            }
            const lisi = new People('lisi',20)
            lisi.sayHi() // lisi 实例对象

 

posted @ 2016-07-07 17:51  yangkangkang  阅读(179)  评论(0编辑  收藏  举报