函数体内有var申明的变量,则只能调用函数体内的变量,没有局部变量才能调用父级函数的变量
函数体内申明变量时若没有var 则相当于申明了一个顶层的全局变量
学习地址:http://blog.csdn.net/yueguanghaidao/article/details/9568071
函数体内没有局部变量 实例如下:
var scope='global';
function t(){
console.log(scope); //global 函数t内没有局部变量scope所以调用父级作用域内的变量scope
scope='local'; //改变全局scope=local
console.log(scope); //local
}
t();
console.log(scope); //local 全局变量已被改
函数体内有var申明的局部变量 实例如下:
var scope='global';
function t(){
console.log(scope); //函数体内有局部变量 预解析时局部scope=undefined;
var scope='local'; //局部scope=local
console.log(scope); //local
}
t();
当函数申明时有参数时,相当于定义了函数体内的局部变量
var scope='global';
function t(scope){ //参数scope相当于定义了函数体内的局部变量
console.log(scope); //undefined
scope='local';
console.log(scope); //local
}
t();
二、函数作用域的嵌套关系是定义时决定的,而不是调用时决定的,也就 是说,JavaScript 的作用域是静态作用域,又叫词法作用域,这是因为作用域的嵌套关系可 以在语法分析时确定,而不必等到运行时确定
var scope='global';
var f1=function(){
console.log(scope);
}
f1();
var f2=function(){
var scope='f2';
f1();
}
f2();
三、例子参悟
var name='window下的name<br/>';
var resultCon;
function fn1(){
resultCon.innerHTML+=name;
}
function MyObj(){
var name='myObj下的name<br/>';
this.doFunction=function(){
resultCon.innerHTML+=name;
}
}
window.οnlοad=function(){
resultCon=document.getElementById('result');
var name='onload下的name<br/>';
var fn2=function(){
resultCon.innerHTML+=name;
}
fn1(); //window下的name
fn2(); //onload下的name
var obj=new MyObj();
obj.doFunction(); //myObj下的name
}
在使用name的值时将“name”用“this.name”来代替会出现什么情况呢,看下例:
var name='window下的name<br/>';
var resultCon;
function fn1(){
resultCon.innerHTML+=this.name;
}
function MyObj(){
var name='myObj下的name<br/>';
this.doFunction=function(){
resultCon.innerHTML+=this.name;
}
}
window.οnlοad=function(){
resultCon=document.getElementById('result');
var name='onload下的name<br/>';
var fn2=function(){
resultCon.innerHTML+=this.name;
}
fn1(); //window下的name
fn2(); //window下的name
var obj=new MyObj();
obj.doFunction(); //this指向实例 undefined
}
以上实例从结果来看可以看出
对于直接定义的函数,this指向window。
对于对象的方法,this指向实例化对象(对应于实例化对象默认返回this的情况)。
也可以看到this和作用域是两套分离的链,遵循个自的变量查询逻辑,具体的查询逻辑在下面的性能分析中会提到。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var name = 'window下的name<br/>';
var resultCon;
function fn1() {
resultCon.innerHTML += this.name;
}
function MyObj() {
var name = 'MyObj下的name<br/>';
this.doFunction = function() {
resultCon.innerHTML += this.name;
};
}
window.onload = function() {
resultCon = document.getElementById('result');
var name = "onload下的name<br/>";
var fn2 = function() {
resultCon.innerHTML += this.name;
};
var myThis = {
name: "自定义的this的name属性<br/>"
};
fn1.call(myThis);//自定义的this的name属性
fn2.call(myThis);//自定义的this的name属性
var obj = new MyObj();
obj.doFunction.call(myThis);//自定义的this的name属性
};
用call/apply改变方法的this指向, 调用时call和apply的使用是为了改变被调用函数的this指向。with的使用是为了改变被调用函数中变量的查询域。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var name = 'window下的name<br/>';
var resultCon;
function fn1(myScope) {
with (myScope) {
resultCon.innerHTML += name;
}
}
function MyObj(myScope) {
var name = 'MyObj下的name<br/>';
this.doFunction = function(myScope) {
with (myScope) {
resultCon.innerHTML += name;
}
};
}
window.onload = function() {
resultCon = document.getElementById('result');
var name = "onload下的name<br/>";
var fn2 = function(myScope) {
with (myScope) {
resultCon.innerHTML += name;
}
};
var myScope = {
name : "自定义变量查询域</br>"
};
fn1(myScope);//自定义变量查询域
fn2(myScope);//自定义变量查询域
var obj = new MyObj();
obj.doFunction(myScope);//自定义变量查询域
};
看到with的使用并不方便,需要在被调用函数中添加with,有人可能想能不能向下面那样调用来整体改变变量作用域而不去改变被调用函数呢?
with (myScope) {
fn1();
fn2();
var obj = new MyObj();
obj.doFunction();
}
很遗憾,不可以!所以在一些成熟的框架中随处可见call和apply的使用,却很少用到with,在用JSHint检测js语法的时候with处都标了小红点,在一些js编码指导中也建议尽量少用with,因为with改变了变量的默认查询链,所以会给后期的维护人员一些困惑,还有性能方面的一些考虑,请慎用with。