函数js原有的:
属性:arguments[]、caller(调用该函数的引用,注意与callee分别开,callee指的是调用函数本身经常在递归中出现)、length(形参个数)、prototype
方法:apply()、call()、bind()、toString()
函数的扩展:
函数参数的默认值
在es6之前不能给函数的参数给定默认值,一般会采用这样的方法:
function a(x,y){
if(typeof y === 'undefined'){
y = 'world';
}
console.log(x,y);
}
es6允许设置默认值,在解构的时候使用模式匹配
function log(x, y = 'World') {
console.log(x, y);
} log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
function foo({x, y = 5}) {
console.log(x, y);
} foo({}) // undefined, 5
foo({x: 1}) // 1, 5
foo({x: 1, y: 2}) // 1, 2
foo() // TypeError: Cannot read property 'x' of undefined
// 写法一:设置了参数对象的解构默认值,但是对象默认为空对象
function m1({x = 0, y = 0} = {}) {
return [x, y];
} // 写法二:设置了参数对象默认是一个不为空的对象
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
} m1() //[0,0]
m2() //[0,0]
m1({x:1}) //[1,0]
m2({x:1}) //[1,undefined]
如果设定了默认参数不在arguments的尾部则在引用函数的时候不能省略,可以用undefined代替
这时函数的length就不是全部的arguments的长度了,而是没有设定默认值的长度
函数作用域:一般而言函数作用域大于全局作用域,但是如果函数的参数为另一函数,则这个另一函数的作用域还是全局作用域
rest参数(...变量名)<=> arguments 用于获取函数多余的参数
rest是一个数组,arguments是一个类数组(对象)
rest只能是最后一个参数,length属性不包括rest参数
扩展运算符(...)将一个数组转为用逗号分隔的参数序列
console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5
可以代替apply方法,将数组转为参数
代替concat <=> [1,2,...[]]
生成数组:[a,...rest] = [1,2,3,4,5]; a= 1;rest = [2,3,4,5];
可以返回多个值,正常函数只能返回数组和对象,但是扩展运算符可以将数组转化
可以将字符串转为数组:[...'he'] = ['h','e'];
name:返回函数名,若为匿名函数则es5返回空字符串,es6返回赋给引用它的变量
构造函数返回函数实例
bind函数返回'bound'+name
箭头函数‘=>’
var f = v => v;
等价于
var f = function(v) {
return v;
};
不需要参数或多个则:用()表示
执行部分不只有返回值,用{},但是如果返回值为对象则需要在外部加() // 正常函数写法
[1,2,3].map(function (x) {
return x * x;
}); // 箭头函数写法
[1,2,3].map(x => x * x);
使用箭头注意点:
(1)函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new
命令,否则会抛出一个错误。
(3)不可以使用arguments
对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield
命令,因此箭头函数不能用作Generator函数。
没有参数的时候就调用外部函数的,同时这时的this也是外部的
函数绑定'::'左边对象右边函数 <=>bind
foo::bar; // 等同于 bar.bind(foo);
尾调用优化
尾调用:某函数最后一步调用另一函数不一定要出现在函数尾部
调用帧:函数调用会在内存形成一个“调用记录”,保存调用位置和内部变量等信息
调用栈:如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。
尾调用优化:只保留内层函数的调用帧,节省内存
注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。
如下代码进行尾调用优化
function f() {
let m = 1;
let n = 2;
return g(m + n);
}
f(); // 等同于
function f() {
return g(3);
}
f(); // 等同于
g(3); 如下代码则不会
function addOne(a){
var one = 1;
function inner(b){
return b + one;
}
return inner(a);
}
尾递归:尾调用自身,不会发生栈溢出
递归非常耗内存,需要同时保存多个调用帧,解决方法:
法一: 确保最后一步只调用自己,把所有用到的内部变量改写成函数的参数
function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
} function factorial(n) {
return tailFactorial(n, 1);
} factorial(5) //
法二:采用ES6的函数默认值
function factorial(n, total = 1) {
if (n === 1) return total;
return factorial(n - 1, n * total);
} factorial(5) //
尾调用优化只在严格模式下开启,正常模式是无效的。
因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。
-
func.arguments
:返回调用时函数的参数。 -
func.caller
:返回调用当前函数的那个函数。
function restricted() {
"use strict";
restricted.caller; // 报错
restricted.arguments; // 报错
}
restricted();
函数内部的最后一个参数可以有尾逗号
ES6入门之函数的扩展的更多相关文章
-
ES6 入门系列 - 函数的扩展
1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...
-
ES6中对函数的扩展
ES6一路扩展,字符串.数组.数值.对象无一“幸免”,ES6说要雨露均沾,函数也不能落下,今天,就来讲解ES6对函数的扩展. 参数的默认值 在开发中,给函数的参数指定默认值,是很普遍很常见的一个需求, ...
-
ES6入门箭头函数
箭头函数: 箭头函数可以与变量结构相结合(箭头函数返回对象的时候必须要在对象外边加()) 注意: 1️⃣函数体内的this是定义时所在的对象,而不是使用时的对象 2️⃣不可以当成构造函数,不可用new ...
-
ES6学习笔记(6)----函数的扩展
参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 函数的扩展 函数的默认值 : ES6可以为函数指定默认值 (1)指定默认值的两种方式 a.函数参 ...
-
ES6入门——函数的扩展
1.函数参数的默认值 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法.现在ES6可以为函数的参数添加默认值,简洁了许多. ES5 function show(a,b){ b = b ...
-
《ES6标准入门》(阮一峰)--8.函数的扩展
1.函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log ...
-
ES6新特性3:函数的扩展
本文摘自ECMAScript6入门,转载请注明出处. 一.函数参数默认值 1. ES6允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') ...
-
ES6 - Note3:数组、对象与函数的扩展
一.数组的扩展,ES6在数组扩展了一些API,以实现更多的功能 1.Array.from:可以将类数组和可遍历的数据结构转换成真正的数组,如下所示 var a = { '0':1,'1':1,leng ...
-
es6入门3--箭头函数与形参等属性的拓展
对函数拓展兴趣更大一点,优先看,前面字符串后面再说,那些API居多,会使用能记住部分就好. 一.函数参数可以使用默认值 1.默认值生效条件 在变量的解构赋值就提到了,函数参数可以使用默认值了.正常我们 ...
随机推荐
-
const
const int i = 20; int const i = 20; 这两个语句是完全相同的:const与int哪个写在前面都不影响语义. 所以: const int *p; int const ...
-
Microsoft.Owin.Hosting 实现启动webapp.dll
Microsoft.Owin.Hosting 下面是 asp.net core 实现 using System;using System.Collections.Generic;using Syste ...
-
烂泥:KVM虚拟机克隆
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上一篇文章介绍了有关KVM虚拟机快照的创建与恢复,这篇文章我们来介绍有关KVM虚拟机克隆. KVM虚拟机的克隆,我们可以分以下几步: 1. 使用virt ...
- iOS log第三方库之间的对比
-
java_小技巧
看很多人说,在Eclipse里面,输入Syso然后按 ALT+/不起作用. 正确的用法如下,先输入一行 System.out.println(); 然后连按5次以上shift键,其实就是粘滞的功能.接 ...
-
[Exchange]2个不同域之间互发邮件
1.互相添加DNS. 不多说,构建信任域也需要这样的 2.DNS中添加Exchange的地址解析. 3.配置Exchange. 在exchange里面添加对方的exchange信息 在Receiver ...
-
ZOJ 2866 Overstaffed Company
树状数组 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...
-
js不需要知道图片宽高的懒加载方法(经过实际测试,不加宽高仍然是无法正常加载的,设置height:auto,height:100%,仍然显示高度为0)
js不需要知道图片宽高的懒加载方法 懒加载是如何实现的? - 简书https://www.jianshu.com/p/e86c61468285找到一个不需要知道图片宽高的懒加载方法了(经过实际测试,不 ...
-
php一致性hash算法
原理部分转自:https://www.jianshu.com/p/e8fb89bb3a61 基本场景 比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object ...
-
Introduction mybatis
项目地址 https://github.com/mybatis/mybatis-3 英文官网 http://mybatis.github.io/mybatis-3/ 中文官网 http://mybat ...