概述
系列
系列列表:
从use strict看JS(一):this与箭头函数
从use strict看JS(二):函数传参模式与arguments
use strict 的 arguments
上一篇说到,use strict对arguments做了以下限定
arguments。不允许对arguments赋值。禁止使用arguments.callee。arguments不再追踪参数的变化
这是为什么呢?如果你明白下面两个例子就不用看这篇文章了~
arguments传的是“值”
function notChangeName(obj){
obj="change";
}
function changeName(obj){
obj.name="change";
}
var dog={
name:"dog"
};
notChangeName(dog);
//输出Object {name: "dog"},没改变
console.log(dog);
changeName(dog);
//输出Object {name: "change"},改了
console.log(dog);
//经典例子,JavaScript高级程序设计的例子
function setName(obj){
obj.name="doge";
obj=new Object();
obj.name="cat";
}
var person={};
setName(person);
//doge
console.log(person.name);
严格模式下arguments会保持对同一“值”的引用
function notChangeName(name){
"use strict";
name="cat";
// 严格模式输出dog,非严格输出cat
console.log(arguments[0]);
}
function changeName(obj){
"use strict";
obj.name="cat";
// 输出cat
console.log(arguments[0].name);
}
notChangeName("dog");
changeName({name:"dog"});
function dog(){
// "use strict";
//严格模式SyntaxError,非严格输出"a"
arguments="a";
console.log(arguments);
}
dog();
arguments & js的变量、值、类型
js的变量、值、类型
js一个变量对应一个值,一个值对应一种类型;而一种类型对应多个值,一个值对应多个变量。
字符串的值不能改变,但能让变量指向不同的值
举两个栗子:
no1.
var dog={
}
var cat=dog;
dog.name="doge";
var third={
name:"the third man"
}
// 输出doge
console.log(cat.name);
上述例子中,dog和cat是不同的变量,但指向同一个值,所以dog改变会反应到cat上。third是另外一个变量,指向不同的值,而这两个值有相同的类型。如下图
no2.
var str="doge";
// 输出o
console.log(str[1]);
str[1]="c";
// 输出o,字符串的值不能改变
console.log(str[1]);
str="cat";
// 输出c,变量指向了不同的值
console.log(str[0]);
arguments传的是值
所以,在前面的例子中,notChangeName函数内部将变量obj指向不同的值,外部的dog指向同一个值且值未发生变化。因而不能改变dog的name。
changeName函数中,obj和dog指向同一个值,更改obj的name就等于更改了dog的name。
JavaScript高级程序设计的例子同理。如下:
function notChangeName(obj){
obj="change";
}
function changeName(obj){
obj.name="change";
}
var dog={
name:"dog"
};
notChangeName(dog);
//输出Object {name: "dog"},没改变
console.log(dog);
changeName(dog);
//输出Object {name: "change"},改了
console.log(dog);
//经典例子,JavaScript高级程序设计的例子
function setName(obj){
obj.name="doge";
obj=new Object();
obj.name="cat";
}
var person={};
setName(person);
//doge
console.log(person.name);
use strict下的arguments会保持对“值”的引用,因而arguments变量是不能被重新赋值的,如果强制赋值呢?比如arguments="a",那就强制报错,没得商量。
也是因为保持对“值”的引用,arguments不再追踪参数的变化,但如果参数是obj且改变的是“值”,而不是重新赋值,那就不一样了。如下:
function notChangeName(name){
"use strict";
name="cat";
// 严格模式输出dog,非严格输出cat
console.log(arguments[0]);
}
function changeName(obj){
"use strict";
obj.name="cat";
// 输出cat
console.log(arguments[0].name);
}
notChangeName("dog");
changeName({name:"dog"});
function dog(){
// "use strict";
//严格模式SyntaxError,非严格输出"a"
arguments="a";
console.log(arguments);
}
dog();
面试会考:arguments不是数组
这就是一个点而已,arguments不是数组,是个类数组对象,没有数组的push、pop、map那些方法,那如何把它变为数组呢?循环遍历一遍也是可以的,arguments有长度,但有更简单的方法,如下:
function argToArr(index){
var newArg=Array.prototype.slice.apply(arguments);
newArg.push(2);
}
argToArr(1);
为何不直接
arguments=Array.prototype.slice.apply(arguments);
因为现在很多都用use strict了,这个会报错,还不知道为何会报错的再看一遍文章哈,自觉点
最后谈谈arguments.callee
这个用来干啥呢,它能在函数内部调用自己,常用来解耦和。比如写个斐波那契数列函数
function fib(n){
if(n===1||n===2){
return 1;
}
return fib(n-1)+fib(n-2);
}
这个问题在哪呢,耦合性太强,改了外层的fib,内部函数名称也得改。可以用arguments.callee改进
function fibArg(n){
if(n===1||n===2){
return 1;
}
return arguments.callee(n-1)+arguments.callee(n-2);
}
问题是这个在严格模式下不能运行。不绕了,来个终极方法
var fib=(function f(n){
"use strict";
if(n===1||n===2){
return 1;
}
return f(n-1)+f(n-2);
})
这种模式之后还会涉及,跟立即执行函数类似,jQuery这些也用了,以后再聊~
等等
好像没谈为何要这样限定arguments!
夜已深,就不继续悟道了。
最后
以上就是真实枕头为你收集整理的 从use strict看JS(二):函数传参模式与arguments的全部内容,希望文章能够帮你解决 从use strict看JS(二):函数传参模式与arguments所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复