JS函数作用域延长的方法

当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始时只包含一个变量,即 arguments 对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。

var color = "blue"; 
function changeColor(){ 
 if (color === "blue"){ 
 color = "red"; 
 } else { 
 color = "blue"; 
 } 
} 
changeColor(); 
alert("Color is now " + color);

在这个简单的例子中,函数 changeColor()的作用域链包含两个对象:它自己的变量对象(其中定义着 arguments 对象)和全局环境的变量对象。可以在函数内部访问变量 color,就是因为可以在这个作用域链中找到它。

延长作用域链(catch、with、call、apply)

虽然执行环境的类型总共只有两种——全局和局部(函数),但还是有其他办法来延长作用域链。这两个语句都会在作用域链的前端添加一个变量对象:try-catch 语句的 catch 块; with 语句。


对with 语句来说,会将指定的对象添加到 作用域链中。对 catch 语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。

例如:

function buildUrl() { 
 var qs = "?debug=true"; 
 with(location){ 
 var url = href + qs; 
 } 
 return url; 
}

这里with接受对是location对象,那么locatiion对象中对属性方法就被添加到了函数到作用域前端。因此函数buildUrl可以引用Location的href(实际上上location.href)


call()和apply() 这两种方法通常用于扩展函数的作用域。

apply(x,y) 接受两个参数,第一个函数上函数作用域;第二个参数上一个数组,它包含函数所要调用的参数,可以用数组实例或者arguments对象。

例如:

function sum(num1, num2){ 
 return num1 + num2; 
} 
function callSum1(num1, num2){ 
 return sum.apply(this, arguments); // 传入 arguments 对象,包含num1,num2
} 
function callSum2(num1, num2){ 
 return sum.apply(this, [num1, num2]); // 传入数组
} 
alert(callSum1(10,10)); //20 
alert(callSum2(10,10)); //20

  这样,callSum1和callSum2就可以调用本来在全局中定义的sum 函数了。

call(x,y,z,...) call接受多个参数,除了第一个参数和apply一样上指定函数的作用域,其余的参数都是调用的参数,用逗号分开。

例如

function sum(num1, num2){ 
 return num1 + num2; 
} 
function callSum(num1, num2){ 
 return sum.call(this, num1, num2); 
} 
alert(callSum(10,10)); //20

使用call和apply扩展函数作用域上很方便的。例如

window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 
} 
sayColor(); //red 
sayColor.call(this); //red 
sayColor.call(window); //red 
sayColor.call(o); //blue

使用call为函数sayColor指定作用域,当指定的作用域为o时,本来的alert(this.color)指向的就是对象o中的color。

除此之外,还有bind方法。它只接受一个参数,指定函数的作用域。例如:

window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 
} 
var objectSayColor = sayColor.bind(o); 
objectSayColor(); //blue

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值