资讯专栏INFORMATION COLUMN

从use strict看JS(二):函数传参模式与arguments

kycool / 2537人阅读

摘要:系列系列列表从看一与箭头函数从看二函数传参模式与的上一篇说到,对做了以下限定。是另外一个变量,指向不同的值,而这两个值有相同的类型。函数中,和指向同一个值,更改的就等于更改了的。可以用改进问题是这个在严格模式下不能运行。

系列

系列列表:
从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!

夜已深,就不继续悟道了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82467.html

相关文章

  • use strictJS(一):this箭头函数

    摘要:其次,指向有一个好处,构造函数一般不要直接运行,那要是强行运行呢指向会给添加许多属性,有扰乱命名空间之嫌,指向之后,你强行运行我就强行报错会给增加属性,改成严格模式就会当然,不能解决所有问题,所以有了箭头函数参考严格模式详解 上github看原文:点一下 系列 一日,见use strict,冥想许久…… 系列列表:从use strict看JS(一):this与箭头函数从use stri...

    darcrand 评论0 收藏0
  • 深入理解ES6笔记(三)函数

    摘要:主要知识点有函数参数默认值剩余参数扩展运算符属性块级函数箭头函数以及尾调用优化深入理解笔记目录函数的默认参数在中,我们给函数传参数,然后在函数体内设置默认值,如下面这种方式。拥有方法的函数被称为构造器。 主要知识点有:函数参数默认值、剩余参数、扩展运算符、new.target属性、块级函数、箭头函数以及尾调用优化showImg(https://segmentfault.com/img/...

    aristark 评论0 收藏0
  • 《深入理解ES6》笔记——函数(3)

    摘要:错误的写法错误的写法中的构造函数新增了支持默认参数和不定参数。箭头函数的简单理解箭头函数的左边表示输入的参数,右边表示输出的结果。但是有了尾调用优化之后,递归函数的性能有了提升。 作为前端切图仔,越发觉得自己离不开函数了。 说到JavaScript函数,脑子里都是匿名函数、普通函数、闭包函数、构造函数......然后还能说出一大堆函数的概念。如果你达到这个水平,那么函数对你来说没有难度...

    DoINsiSt 评论0 收藏0
  • 前端面经整理之JS和CSS

    摘要:作为对象原型链的终点。调用函数时,应该提供的参数没有提供,该参数等于。它可以用于引用该函数的函数体内当前正在执行的函数。 一 JS 二 CSS 一 JS ==和===的区别 ===叫做严格运算符 ==叫做相等运算符严格运算符比较时不仅仅比较数值还要比较数据类型是否一样相等运算符在比较相同类型的数据时,与严格相等运算符完全一样。 在比较不同类型的数据时,相等运算符会先将数据进行类型转换,...

    stonezhu 评论0 收藏0

发表评论

0条评论

kycool

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<