您的位置:奥门新浦京网址 > Wed前段 > 优雅的数组降维,函数中的

优雅的数组降维,函数中的

发布时间:2019-11-06 14:11编辑:Wed前段浏览(75)

    能够安装arguments对象

    你能够在arguments对象数组中装置一定的项。首先,你能够使用索引0设置数组的首先个项,如下所示:

    function add(num1, num2) { arguments[0] = 15; var res = num1 + num2; return res; } var r = add(7, 8); console.log(r);

    1
    2
    3
    4
    5
    6
    7
    function add(num1, num2) {
        arguments[0] = 15;
        var res = num1 + num2;
        return res;
    }
    var r = add(7, 8);
    console.log(r);

    在add函数中,num1和arguments[0]援用相仿的值。所以,当你更新arguments[0]时,num1的值也会被更新。对于地点的代码,输出将是23。

    深入显出妙用 Javascript 中 apply、call、bind

    2015/09/24 · JavaScript · 4 评论 · apply, bind, call

    正文小编: 伯乐在线 - chokcoco 。未经作者许可,防止转发!
    应接加入伯乐在线 专辑作者。

    那篇作品实乃很难下笔,因为网络有关小说无尽。

    戏剧性的是昨日看见阮老师的豆蔻年华篇作品的一句话:

    “对本身来讲,博客首先是后生可畏种知识管理工科具,其次才是流传工具。笔者的技术文章,首要用来整合治理本身还不懂的学识。小编只写那么些本人还从未完全理解的事物,那多少个自个儿了然的东西,往往未有重力写。炫丽没有是自身的念头,好奇才是。”

    对于那句话,无法扶助越来越多,也让本人下决心好好写那篇,网络随笔虽多,许多复制粘贴,且晦涩难懂,小编梦想可以因此那篇小说,能够清晰的提拔对apply、call、bind的认知,而且列出大器晚成部分它们的妙用加深回想。

       apply、call

    在 javascript 中,call 和 apply 皆感觉着更动有些函数运转时的上下文(context卡塔 尔(阿拉伯语:قطر‎而存在的,换句话说,就是为了转移函数体内部 this 的针对。

    JavaScript 的一大特色是,函数存在「定义时上下文」和「运维时上下文」以至「上下文是能够变动的」那样的概念。

    先来二个板栗:

    JavaScript

    function fruits() {} fruits.prototype = { color: "red", say: function() { console.log("My color is " + this.color); } } var apple = new fruits; apple.say(); //My color is red

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function fruits() {}
     
    fruits.prototype = {
        color: "red",
        say: function() {
            console.log("My color is " + this.color);
        }
    }
     
    var apple = new fruits;
    apple.say();    //My color is red

    可是只要大家有三个指标banana= {color : “yellow”} ,大家不想对它再也定义 say 方法,那么我们能够透过 call 或 apply 用 apple 的 say 方法:

    JavaScript

    banana = { color: "yellow" } apple.say.call(banana); //My color is yellow apple.say.apply(banana); //My color is yellow

    1
    2
    3
    4
    5
    banana = {
        color: "yellow"
    }
    apple.say.call(banana);     //My color is yellow
    apple.say.apply(banana);    //My color is yellow

    之所以,可以观察 call 和 apply 是为着动态改换 this 而产出的,当叁个 object 没有某些方法(本栗子中banana未有say方法卡塔 尔(英语:State of Qatar),然则别的的有(本栗子中apple有say方法卡塔尔,我们得以正视call或apply用别的对象的主意来操作。

    apply、call 的区别

    对于 apply、call 二者来说,功效完全等同,只是选拔参数的主意不太相通。举个例子,有七个函数定义如下:

    JavaScript

    var func = function(arg1, arg2) { };

    1
    2
    3
    var func = function(arg1, arg2) {
     
    };

    就能够通过如下形式来调用:

    JavaScript

    func.call(this, arg1, arg2); func.apply(this, [arg1, arg2])

    1
    2
    func.call(this, arg1, arg2);
    func.apply(this, [arg1, arg2])

    里头 this 是你想内定的上下文,他得以是此外七个 JavaScript 对象(JavaScript 中漫天皆对象),call 须求把参数按梯次传递步入,而 apply 则是把参数放在数组里。

    JavaScript 中,某些函数的参数数量是不稳定的,因而要说适用条件的话,当您的参数是大名鼎鼎掌握多少时用 call 。

    而不分明的时候用 apply,然后把参数 push 进数组传递走入。当参数数量不确定期,函数内部也足以由此 arguments 那么些数组来遍历全数的参数。

    为了加固加强回想,上边列举部分常用用法:

    1、数组之间追加

    JavaScript

    var array1 = [12 , "foo" , {name "Joe"} , -2458]; var array2 = ["Doe" , 555 , 100]; Array.prototype.push.apply(array1, array2); /* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

    1
    2
    3
    4
    var array1 = [12 , "foo" , {name "Joe"} , -2458];
    var array2 = ["Doe" , 555 , 100];
    Array.prototype.push.apply(array1, array2);
    /* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

    2、获取数组中的最大值和最小值

    JavaScript

    var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers = Math.max.apply(Math, numbers), //458 maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

    1
    2
    3
    var  numbers = [5, 458 , 120 , -215 ];
    var maxInNumbers = Math.max.apply(Math, numbers),   //458
        maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

    number 本人并未有 max 方法,不过 Math 有,我们就足以注重 call 大概 apply 使用其情势。

    3、验证是还是不是是数组(前提是toString()方法未有被重写过卡塔尔

    JavaScript

    functionisArray(obj){ returnObject.prototype.toString.call(obj) === '[object Array]' ; }

    1
    2
    3
    functionisArray(obj){
        returnObject.prototype.toString.call(obj) === '[object Array]' ;
    }

    4、类(伪卡塔尔国数组使用数组方法

    JavaScript

    var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

    1
    var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

    Javascript中设有生机勃勃种名字为伪数组的对象协会。相比较特别的是 arguments 对象,还会有像调用 getElementsByTagName , document.childNodes 之类的,它们再次来到NodeList对象都归属伪数组。不能够采取Array下的 push , pop 等艺术。

    只是大家能经过 Array.prototype.slice.call 调换为确实的数组的含有 length 属性的靶子,那样 domNodes 就可以使用 Array 下的具有办法了。

    长远领会运用apply、call

    下面就借用生龙活虎道面试题,来更深刻的去领略下 apply 和 call 。

    概念二个 log 方法,让它能够代办 console.log 方法,多如牛毛的消除办法是:

    JavaScript

    function log(msg) { console.log(msg); } log(1); //1 log(1,2); //1

    1
    2
    3
    4
    5
    function log(msg) {
      console.log(msg);
    }
    log(1);    //1
    log(1,2);    //1

    地点方法可以减轻最主题的要求,但是当传入参数的个数是不分明的时候,上边的点子就失效了,这时就足以考虑选拔apply 或许call,注意这里传出多少个参数是不鲜明的,所以使用apply是最棒的,方法如下:

    JavaScript

    function log(){ console.log.apply(console, arguments); }; log(1); //1 log(1,2); //1 2

    1
    2
    3
    4
    5
    function log(){
      console.log.apply(console, arguments);
    };
    log(1);    //1
    log(1,2);    //1 2

    接下去的要求是给每三个 log 新闻增加一个”(app)”的前辍,举个例子:

    JavaScript

    log("hello world"); //(app)hello world

    1
    log("hello world");    //(app)hello world

    该怎么办相比文雅呢?那时候供给想到arguments参数是个伪数组,通过 Array.prototype.slice.call 转化为正式数组,再采用数组方法unshift,像这么:

    JavaScript

    function log(){ var args = Array.prototype.slice.call(arguments); args.unshift('(app)'); console.log.apply(console, args); };

    1
    2
    3
    4
    5
    6
    function log(){
      var args = Array.prototype.slice.call(arguments);
      args.unshift('(app)');
     
      console.log.apply(console, args);
    };

    bind

    说罢了 apply 和 call ,再来讲说bind。bind() 方法与 apply 和 call 很日常,也是可以改换函数体内 this 的指向。

    MDN的疏解是:bind()方法会创制叁个新函数,称为绑定函数,当调用这几个绑定函数时,绑定函数会以创办它时传出 bind()方法的第四个参数作为 this,传入 bind() 方法的第2个以致之后的参数加上绑定函数运营时笔者的参数遵照顺序作为原函数的参数来调用原函数。

    直白来拜谒实际什么运用,在科学普及的单人体模型式中,平常大家会选择 _this , that , self 等保存 this ,那样大家能够在改变了上下文之后三回九转引用到它。 像这样:

    JavaScript

    var foo = { bar : 1, eventBind: function(){ var _this = this; $('.someClass').on('click',function(event) { /* Act on the event */ console.log(_this.bar); //1 }); } }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var foo = {
        bar : 1,
        eventBind: function(){
            var _this = this;
            $('.someClass').on('click',function(event) {
                /* Act on the event */
                console.log(_this.bar);     //1
            });
        }
    }

    由于 Javascript 特有的建制,上下文遭遇在 eventBind:function(){ } 过渡到 $(‘.someClass’).on(‘click’,function(event) { }) 产生了改变,上述使用变量保存 this 那些措施都以行得通的,也从未怎么难题。当然使用 bind() 能够进一层文雅的减轻这些难点:

    JavaScript

    var foo = { bar : 1, eventBind: function(){ $('.someClass').on('click',function(event) { /* Act on the event */ console.log(this.bar); //1 }.bind(this)); } }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var foo = {
        bar : 1,
        eventBind: function(){
            $('.someClass').on('click',function(event) {
                /* Act on the event */
                console.log(this.bar);      //1
            }.bind(this));
        }
    }

    在上述代码里,bind() 创立了二个函数,当那么些click事件绑定在被调用的时候,它的 this 关键词会被设置成被传出的值(这里指调用bind()时传出的参数卡塔尔国。由此,这里大家传入想要的内外文 this(其实正是 foo ),到 bind() 函数中。然后,当回调函数被施行的时候, this 便指向 foo 对象。再来二个轻松的板栗:

    JavaScript

    var bar = function(){ console.log(this.x); } bar(); // undefined var func = bar.bind(foo); func(); // 3

    1
    2
    3
    4
    5
    6
    7
    var bar = function(){
        console.log(this.x);
    }
     
    bar(); // undefined
    var func = bar.bind(foo);
    func(); // 3

    此间我们创制了三个新的函数 func,当使用 bind() 创造贰个绑定函数之后,它被实行的时候,它的 this 会被设置成 foo , 并非像大家调用 bar() 时的全局成效域。

    有个风趣的主题材料,假如连接 bind() 三次,亦或然是三回九转 bind() 壹遍那么输出的值是怎么样啊?像那样:

    JavaScript

    var bar = function(){ console.log(this.x); } var foo = { x:3 } var sed = { x:4 } var func = bar.bind(foo).bind(sed); func(); //? var fiv = { x:5 } var func = bar.bind(foo).bind(sed).bind(fiv); func(); //?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var bar = function(){
        console.log(this.x);
    }
    var foo = {
        x:3
    }
    var sed = {
        x:4
    }
    var func = bar.bind(foo).bind(sed);
    func(); //?
     
    var fiv = {
        x:5
    }
    var func = bar.bind(foo).bind(sed).bind(fiv);
    func(); //?

    答案是,五遍都仍将出口 3 ,而非期望中的 4 和 5 。原因是,在Javascript中,数十次 bind() 是无效的。更深档期的顺序的原原本本的经过, bind() 的贯彻,相当于接纳函数在里头包了一个 call / apply ,第一次 bind() 相当于再包住第二次 bind() ,故第二回之后的 bind 是爱莫能助生效的。

    apply、call、bind比较

    那就是说 apply、call、bind 三者绝相比较,之间又有怎么着异同呢?几时使用 apply、call,曾几何时使用 bind 呢。简单的二个尖栗:

    JavaScript

    var obj = { x: 81, }; var foo = { getX: function() { return this.x; } } console.log(foo.getX.bind(obj)()); //81 console.log(foo.getX.call(obj)); //81 console.log(foo.getX.apply(obj)); //81

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var obj = {
        x: 81,
    };
     
    var foo = {
        getX: function() {
            return this.x;
        }
    }
     
    console.log(foo.getX.bind(obj)());  //81
    console.log(foo.getX.call(obj));    //81
    console.log(foo.getX.apply(obj));   //81

    多少个出口的都是81,然则注意看使用 bind() 方法的,他前面多了对括号。

    也正是说,差距是,当您期待改换上下文景况之后并不是立时奉行,而是回调试行的时候,使用 bind() 方法。而 apply/call 则会立时实行函数。

    再计算一下:

    • apply 、 call 、bind 三者都以用来改造函数的this对象的针没有错;
    • apply 、 call 、bind 三者第二个参数都以this要照准的对象,也正是想内定的上下文;
    • apply 、 call 、bind 三者都足以使用一而再一而再参数字传送参;
    • bind 是回来对应函数,便于稍后调用;apply 、call 则是那时调用 。

    正文实例现身的持有代码,在自家的github上得以下载。

    打赏支持作者写出更加多好作品,多谢!

    打赏小编

    高贵的数组降维——Javascript中apply方法的妙用

    2016/02/18 · JavaScript · apply, 数组

    初藳出处: ralph_zhu   

    将多维数组(特别是二维数组卡塔 尔(阿拉伯语:قطر‎转变为风姿洒脱维数组是职业支付中的常用逻辑,除了利用节约能源的大循环转变以外,大家还足以选拔Javascript的言语特色实现特别轻巧高贵的更动。本文将从节俭的轮回转变初阶,逐条介绍三种常用的调换方法,并借此简单回想Array.prototype.concat方法和Function.prototype.apply方法。
    以下代码将以把二维数组降维到豆蔻年华维数组为例。

    1. 勤政的转变

    JavaScript

    function reduceDimension(arr) { var reduced = []; for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].length; j++) { reduced.push(arr[i][j]); } } return reduced; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function reduceDimension(arr) {
        var reduced = [];
        for (var i = 0; i < arr.length; i++) {
            for (var j = 0; j < arr[i].length; j++) {
                reduced.push(arr[i][j]);
            }
        }
        return reduced;
    }

    此办法思路轻巧,利用再度循环遍历二维数组中的每一个元素并放置新数组中。

     

    1. 利用concat转换
      先来回想一下MDN上对此该办法的介绍:
      “concat creates a new array consisting of the elements in the object on which it is called, followed in order by, for each argument, the elements of that argument (if the argument is an array) or the argument itself (if the argument is not an array).”

    即如若concat方法的参数是二个成分,该因素会被间接插入到新数组中;若是参数是三个数组,该数组的逐生机勃勃要素将被插入到新数组中;将该天性应用到代码中:

    JavaScript

    function reduceDimension(arr) { var reduced = []; for (var i = 0; i < arr.length; i++){ reduced = reduced.concat(arr[i]); } return reduced; }

    1
    2
    3
    4
    5
    6
    7
    function reduceDimension(arr) {
        var reduced = [];
        for (var i = 0; i < arr.length; i++){
            reduced = reduced.concat(arr[i]);
        }
        return reduced;
    }

    arr的每一个成分都是一个数组,作为concat方法的参数,数组中的每一个子成分又都会被单独插入进新数组。
    行使concat方法,大家将再也循环简化为了单重循环。

     

    1. 利用apply和concat转换
      固守惯例,先来回看一下MDN上对此apply方法的介绍:
      “The apply() method calls a function with a given this value and arguments provided as an array.”

    即apply方法会调用多少个函数,apply方法的第三个参数会作为被调用函数的this值,apply方法的第叁个参数(一个数组,或类数组的靶子卡塔 尔(英语:State of Qatar)会作为被调用对象的arguments值,约等于说该数组的顺序要素将会相继成为被调用函数的相继参数;将该脾性应用到代码中:

    function reduceDimension(arr) { return Array.prototype.concat.apply([], arr); }

    1
    2
    3
    function reduceDimension(arr) {
        return Array.prototype.concat.apply([], arr);
    }

    arr作为apply方法的第一个参数,本人是一个数组,数组中的每三个成分(依旧数组,即二维数组的第二维卡塔尔会被充当参数依次传入到concat中,效果等同[].concat([1,2], [3,4], [5,6])。
    使用apply方法,大家将单重循环优化为了生机勃勃行代码,很简短有型有木有啊~

    读者也可参看本文思路,自个儿使用递归落成N维数组降维的逻辑。

    3 赞 8 收藏 评论

    图片 1

    将arguments对象转变为数组

    正如作者辈在这里篇文章中介绍的那样,JavaScript函数arguments对象不是纯数组。除了长度属性外,它未有别的其它品质。但是,你能够动用Array.prototype.slice.call将arguments对象调换为数组,如下所示:

    function add(num1, num2) { var arg = Array.prototype.slice.call(arguments); console.log(arg.pop()); }

    1
    2
    3
    4
    function add(num1, num2) {
        var arg = Array.prototype.slice.call(arguments);
        console.log(arg.pop());
    }

    在ECMAScript 6中,你能够将arguments对象转变为一个数组,如下所示:

    function add(num1, num2) { var arg = Array.from(arguments); console.log(arg.pop()); }

    1
    2
    3
    4
    function add(num1, num2) {
        var arg = Array.from(arguments);
        console.log(arg.pop());
    }

    有关笔者:chokcoco

    图片 2

    经不住光阴似箭,逃可是此间少年。 个人主页 · 我的篇章 · 63 ·    

    图片 3

    本文由奥门新浦京网址发布于Wed前段,转载请注明出处:优雅的数组降维,函数中的

    关键词:

上一篇:没有了

下一篇:没有了