作用域和闭包

162 阅读1分钟

1,执行上下文

范围:一段 <script> 或者一个函数

全局变量对象:变量定义、函数声明

函数内变量对象:变量定义、函数声明、this、arguments

示例

console.log(a)        //undefined
var a = 100         

fn('zhangsan')        //'zhangsan',20
function fn(name) {
    age = 20
    console.log(name, age)
    var age
}

以上示例中,在执行第一行之前,会先将函数fn取出放在前面,将 a 取出赋值为 undefined,而在执行过程中,第二行才赋值了 100,所以第一行结果是 undefined

在 fn 函数中,会先将 name 取出赋值,然后是 age 取出先赋值为 undefined,在函数执行中,先赋值了再打印,故都有值

a,在创建执行上下文阶段:

先创建 arguments 对象(函数),函数先取出放前面,变量先取出放前面定义为 undefined

b,执行阶段

执行代码,函数运行,确定this指向

2,this指向

this 要在执行时才能确认值,定义时无法确认,有如下几种情况

  1. 作为构造函数执行
  2. 作为对象属性执行
  3. 作为普通函数执行
  4. call、apply、bind

通过以下几个示例,我们便能清楚了解 this 在不同情况下的区别啦

function Foo(name) {
    this.name = name
}
//作为构造函数执行
var a = new Foo('zhangsan')  //this === a
console.log(a.name) //zhangsan

var a = {
    name: 'A',
    fn: function() {
        console.log(this.name)
    }
}
//作为对象属性执行
a.fn()                    //this === a
//通过call指向
a.fn.call({name: 'B'})    //this === {name: 'B'}
//下行代码执行后,fn1是个普通函数,作为普通函数执行
var fn1 = a.fn
fn1()                    //this === window


function fn1(name, age) {
    alert(name)
    console.log(this)
}

//通过call指向
fn1.call({x: 100}, 'zhangsan', 20)  //this === {x: 100}

//通过bind指向
var fn2 = function(name, age) {
    alert(name)
    console.log(this)
}.bind({y: 200})

fn2('zhangsan', 20)               //this === {y: 200}

3,作用域