ECMAScript6(5):函数的扩展,web前端开发教程视频

通过上面这个例子不难发现, 不仅可以用解构的方法设置初始值, 还可以进行参数传递。当然, 这里也可以是对象形式的解构赋值。如果传入的参数无法解构, 就会报错:

function fun1({a=1, b=5, c=‘A’}){

console.log(c + (a + b));

}

fun1({}); //‘A6’

fun1(); //TypeError, 因为无法解构

//但这样设计函数对使用函数的码农很不友好

//所以, 技巧:

function fun2({a=1, b=5, c=‘A’}={}){

console.log(c + (a + b));

}

fun2(); //‘A6’

注意, 其实还有一种方法, 但不如这个好, 我们比较如下:

//fun1 比 fun2 好, 不会产生以外的 undefined

function fun1({a=1, b=5, c=‘A’}={}){

console.log(c + (a + b));

}

function fun2({a, b, c}={a: 1, b: 5, c: ‘A’}){

console.log(c + (a + b));

}

//传了参数, 但没传全部参数就会出问题

fun1({a: 8}); //‘A13’

fun2({a: 8}); //NaN

不过这里强烈建议, 将具有默认值的参数排在参数列表的后面。否则调用时依然需要传参:

function f1(a=1, b){

console.log(a + b);

}

function f2(a, b=1){

console.log(a + b);

}

f2(2); //3

f1(, 2); //报错

f1(undefined, 2); //3, 注意这里不能用 null 触发默认值

这里我们还需要单独讨论一下默认参数对 arguments 的影响:

function foo(a = 1){

console.log(a, arguments[0]);

}

foo(); //1 undefined

foo(undefined); //1 undefined

foo(2); //2 2

foo(null); //null null

很明显,默认参数并不能加到 arguments 中。

  • 函数的 length 属性

这个属性ES6 之前就是存在的, 记得length表示预计传入的形参个数, 也就是没有默认值的形参个数:

(function(a){}).length; //1

(function(a = 5){}).length; //0

(function(a, b, c=5){}).length; //2

(function(…args){}).length; //0, rest参数也不计入 length

rest 参数

rest 参数形式为 ...变量名, 它会将对应的全部实际传递的变量放入数组中, 可以用它来替代 arguments:

function f(…val){

console.log(val.join());

}

f(1, 2); //[1, 2]

f(1, 2, 3, 4); //[1, 2, 3, 4]

function g(a, …val){

console.log(val.join());

}

g(1, 2); //[2]

g(1, 2, 3, 4); //[2, 3, 4]

否则这个函数 g 你的这样定义函数, 比较麻烦:

function g(a){

console.log([].slice.call(arguments, 1).join());

}

这里需要注意2点:

  • rest参数必须是函数的最后一个参数, 它的后面不能再定义参数, 否则会报错。

  • rest参数不计入函数的 length 属性中

建议:

  • 所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数。这样方便调用者以任何顺序传递参数。

  • 不要在函数体内使用arguments变量,使用rest运算符(…)代替。因为rest运算符显式表明你想要获取参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。

  • 使用默认值语法设置函数参数的默认值。

扩展运算符

扩展运算符类似 rest运算符的逆运算, 用 ... 表示, 放在一个(类)数组前, 将该数组展开成独立的元素序列:

console.log(1, …[2, 3, 4], 5); //输出1, 2, 3, 4, 5

扩展运算符的用处很多:

- 可以用于快速改变类数组对象为数组对象, 也是用于其他可遍历对象:

[…document.querySelectorAll(‘li’)]; //[

  • ,
  • ,
  • ];
    • 结合 rest 参数使函数事半功倍:

    function push(arr, …val){

    return arr.push(…val); //调用函数时, 将数组变为序列

    }

    • 替代 apply 写法

    var arr = [1, 2, 3];

    var max = Math.max(…arr); //3

    var arr2 = [4, 5, 6];

    arr.push(…arr2); //[1, 2, 3, 4, 5, 6]

    new Date(…[2013, 1, 1]); //ri Feb 01 2013 00: 00: 00 GMT+0800 (CST)

    • 连接, 合并数组

    var more = [4, 5];

    var arr = [1, 2, 3, …more]; //[1, 2, 3, 4, 5]

    var a1 = [1, 2];

    var a2 = [3, 4];

    var a3 = [5, 6];

    var a = […a1, …a2, …a3]; //[1, 2, 3, 4, 5, 6]

    • 解构赋值

    var a = [1, 2, 3, 4, 5];

    var [a1, …more] = a; //a1 = 1, more = [2, 3, 4, 5]

    //注意, 扩展运算符必须放在解构赋值的结尾, 否则报错

    • 字符串拆分

    var str = “hello”;

    var alpha = […str]; //alpha = [‘h’, ‘e’, ‘l’, ‘l’, ‘o’]

    […‘x\uD83D\uDE80y’].length; //3, 正确处理32位 unicode 字符

    建议:使用扩展运算符(…)拷贝数组。

    name 属性

    name 属性返回函数的名字, 对于匿名函数返回空字符串。不过对于表达式法定义的函数, ES5 和 ES6有差别:

    var fun = function(){}

    fun.name; //ES5: “”, ES6: “fun”

    (function(){}).name; //“”

    对于有2个名字的函数, 返回后者, ES5 和 ES6没有差别:

    var fun = function baz(){}

    fun.name; //baz

    对于 Function 构造函数得到的函数, 返回 anonymous:

    new Function(“fun”).name; //“anonymous”

    new Function().name; //“anonymous”

    (new Function).name; //“anonymous”

    对于 bind 返回的函数, 加上 bound 前缀

    function f(){}

    f.bind({}).name; //“bound f”

    (function(){}).bind({}).name; //"bound "

    (new Function).bind({}).name; //“bound anonymous”

    箭头函数

    箭头函数的形式如下:

    var fun = (参数列表) => {函数体};

    如果只有一个参数(且不指定默认值), 参数列表的圆括号可以省略; (如果没有参数, 圆括号不能省略)

    如果只有一个 return 语句, 那么函数体的花括号也可以省略, 同时省略 return 关键字。

    var fun = value => value + 1;

    //等同于

    var fun = function(value){

    return value + 1;

    }

    var fun = () => 5;

    //等同于

    var fun = function(){

    return 5;

    }

    如果箭头函数的参数或返回值有对象, 应该用 () 括起来:

    var fun = n => ({name: n});

    var fun = ({num1=1, num2=3}={}) => num1 + num2;

    看完之前的部分, 箭头函数应该不陌生了:

    var warp = (…val) => val;

    var arr1 = warp(2, 1, 3); //[2, 1, 3]

    var arr2 = arr1.map(x => x * x); //[4, 1, 9]

    arr2.sort((a, b) => a - b); //[1, 4, 9]

    使用箭头函数应注意以下几点:

    - 不可以将函数当做构造函数调用, 即不能使用 new 命令;

    - 不可以在箭头函数中使用 yield 返回值, 所以不能用过 Generator 函数;

    - 函数体内不存在 arguments 参数;

    - 函数体内部不构成独立的作用域, 内部的 this 和定义时候的上下文一致; 但可以通过 call, apply, bind 改变函数中的 this。关于作用域, 集中在ES6函数扩展的最后讨论。

    举几个箭头函数的实例:

    实例1: 实现功能如: insert(2).into([1, 3]).after(1)insert(2).into([1, 3]).before(3)这样的函数:

    var insert = value => ({

    into: arr => ({

    before: val => {

    arr.splice(arr.indexOf(val), 0, value);

    return arr;

    },

    after: val => {

    arr.splice(arr.indexOf(val) + 1, 0, value);

    return arr;

    }

    })

    });

    console.log(insert(2).into([1, 3]).after(1));

    console.log(insert(2).into([1, 3]).before(3));

    实例2: 构建一个管道(前一个函数的输出是后一个函数的输入):

    var pipe = (…funcs) => (init_val) => funcs.reduce((a, b) => b(a), init_val);

    //实现 2 的 (3+2) 次方

    var plus = a => a + 2;

    pipe(plus, Math.pow.bind(null, 2))(3); //32

    实例3: 实现 λ 演算

    //fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))

    var fix = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));

    小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

    深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
    因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

    img
    img
    img
    img

    由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

    如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
    img

    后话

    开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

    对于面试,说几句个人观点。

    面试,说到底是一种考试。正如我们一直批判应试教育脱离教育的本质,为了面试学习技术也脱离了技术的初心。但考试对于人才选拔的有效性是毋庸置疑的,几千年来一直如此。除非你有实力向公司证明你足够优秀,否则,还是得乖乖准备面试。这也并不妨碍你在通过面试之后按自己的方式学习。
    其实在面试准备阶段,个人的收获是很大的,我也认为这是一种不错的学习方式。首先,面试问题大部分基础而且深入,这些是平时工作的基础。就好像我们之前一直不明白学习语文的意义,但它的意义就在每天的谈话间。

    92945208)]
    [外链图片转存中…(img-TsmTHKgq-1710592945208)]

    由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

    如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
    [外链图片转存中…(img-epXQtQYn-1710592945209)]

    后话

    开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

    对于面试,说几句个人观点。

    面试,说到底是一种考试。正如我们一直批判应试教育脱离教育的本质,为了面试学习技术也脱离了技术的初心。但考试对于人才选拔的有效性是毋庸置疑的,几千年来一直如此。除非你有实力向公司证明你足够优秀,否则,还是得乖乖准备面试。这也并不妨碍你在通过面试之后按自己的方式学习。
    其实在面试准备阶段,个人的收获是很大的,我也认为这是一种不错的学习方式。首先,面试问题大部分基础而且深入,这些是平时工作的基础。就好像我们之前一直不明白学习语文的意义,但它的意义就在每天的谈话间。

    所谓面试造火箭,工作拧螺丝。面试往往有更高的要求,也迫使我们更专心更深入地去学习一些知识,也何尝不是一种好事。

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值