js 是解释型语言不是编译型语言,所以有些错误在编写程序时不会报错,什么时候执行什么时候报错。 范围:一段script标签或者一个函数之内都会生成一个上下文 全局:变量定义,函数声明 //执行之前,一段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; }this要在执行时才能确认值,定义时无法确认
var a={ name:"A", fn:function(){ console.log(this.name) } } a.fn() //this===a a.fn.call({name:B}) //this==={name:'B'} var fn1=a.fn; fn1() //this===window 使用场景 ①作为构造函数执行 function Foo(name){ //this={}; this.name=name; //return this } var f=new Foo('zhangsan') ②作为对象属性执行 var obj={ name:'A', printName:function(){ console.log(this.name) } } obj.printName(); ③作为普通函数执行 function fn(){ console.log(this) //this===window } fn() ④call apply bind function fn1(name,age){ alert(name); console.log(this) //this===window } fn1.call({x:100},'zhangsan',20) fn1.apply({x:100},['zhangsan',20]) var fn2=function(name,age){ alert(name); console.log(this) //this==={x:100} }.bind({x:100})//bind只能用函数表达式,函数声明不可用,会报错 fn2('zhangsan',200)注意:函数的父级作用域是函数定义时候的作用域,不是函数执行时候的作用域,也就是说那个作用域定义了这个函数,这个函数的父级作用域就是谁,跟函数执行没有关系,函数自由变量要到父级作用域中找,就形成了作用域链。
实际开发中闭包的应用:封装变量,收敛权限
function F1(){ var a=100; //返回一个函数(函数作为返回值) return function(){ console.log(a);//自由变量,父作用域寻找 } } //f1得到一个函数 var f1=F1(); var a=200; f1();//100= 闭包使用场景 ①函数作为返回值 ②函数作为参数传递(函数自由变量要到父级作用域中找) function F1(){ var a=100; return function(){ console.log(a); } } var f1=F1(); function F2(fn){ var a=200 fn();(自由变量要到声明定义时的父作用域中找,和执行的作用域没有关系) } F2(f1);//100①变量的定义 ②函数的声明(注意和函数表达式的区别)
参考上文this