JS 函数
https://developer.mozilla.org/zh-CN/docs/Web/API
定义函数
function sayHi(name, message) {
alert("Hello " + name + "," + message);
}
调用函数
sayHi("Nicholas", "how are you today?");
ECMAScript 中的函数在定义时不必指定是否返回值
形参和实参
函数定义的参数为形参,调用时的参数是实参
调用时:
如果形参数量多于实参,则多出的形参会被忽略
如果实参数量多于形参,则多出的实参会复制为undefined
剩余参数 es6
function t(a, ...arr) { console.log(arr) } t(1, 2, 4, 5)
默认参数 es6
function t(a, b=3) { console.log(b) } t(1)
隐式函数参数arguments es5
function t(a,b) { console.log(a) console.log(arguments[1]) } t(1,2)
实际上argument是参数的别名,赋值后对应的参数值也会改变
function t(a) { console.log(arguments[0]) arguments[0]=666 console.log(a) } t(1)
严格模式下不能使用
"use strict" function t(a) { console.log(arguments[0]) arguments[0]=666 console.log(a) } t(1)
隐式函数参数this
在浏览器中,以函数方式调用,this是windows的对象。以方法调用,this是该调用的对象
理解参数
ECMAScript 函数的参数与大多数其他语言中函数的参数有所不同。 ECMAScript 函数不介意传递进
来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数,
在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不
会有什么怨言。之所以会这样,原因是 ECMAScript 中的参数在内部是用一个数组来表示的。函数接收
到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任
何元素,无所谓;如果包含多个元素,也没有问题。实际上,在函数体内可以通过 arguments 对象来
访问这个参数数组,从而获取传递给函数的每一个参数。
其实, arguments 对象只是与数组类似(它并不是 Array 的实例),因为可以使用方括号语法访
问它的每一个元素(即第一个元素是 arguments[0],第二个元素是 argumetns[1],以此类推),使
用 length 属性来确定传递进来多少个参数。在前面的例子中, sayHi()函数的第一个参数的名字叫
name,而该参数的值也可以通过访问 arguments[0]来获取。因此,那个函数也可以像下面这样重写,
即不显式地使用命名参数:
function sayHi() { alert("Hello " + arguments[0] + "," + arguments[1]); } FunctionExample05.
这个重写后的函数中不包含命名的参数。虽然没有使用 name 和 message 标识符,但函数的功能
依旧。这个事实说明了 ECMAScript 函数的一个重要特点:命名的参数只提供便利,但不是必需的。另
外,在命名参数方面,其他语言可能需要事先创建一个函数签名,而将来的调用必须与该签名一致。但
在 ECMAScript 中,没有这些条条框框,解析器不会验证命名参数。
通过访问 arguments 对象的 length 属性可以获知有多少个参数传递给了函数。下面这个函数会
在每次被调用时,输出传入其中的参数个数:
function howManyArgs() { alert(arguments.length); } howManyArgs("string", 45); //2 howManyArgs(); //0 howManyArgs(12); //1
function doAdd() { if(arguments.length == 1) { alert(arguments[0] + 10); } else if (arguments.length == 2) { alert(arguments[0] + arguments[1]); } } doAdd(10); //20 doAdd(30, 20); //50
没有重载
如果在 ECMAScript 中定义了两个名字相同的函数,则该名字只属于后定义的函数
function addSomeNumber(num){ return num + 100; } function addSomeNumber(num) { return num + 200; } var result = addSomeNumber(100); //300
回调函数
var values=[1,4,5,2,3] var s=values.sort(function(a,b){ return a-b }) console.log(s)
自记忆函数
function t() { if (!t.cache) { console.log('create') t.cache = 'ok' } console.log('end') } t() t()
立即执行函数
函数外包裹一个括号,
let l=(function (a,b){return a+b})(3,2) console.log(l)
箭头函数 es6
let l=(a,b)=>a+b
console.log(l(2,3))
参数只有一个时,可以缺略括号
构造函数
构造函数和函数定义相同,在调用的时候才进行区分。
使用new关键字调用函数,那么这个函数就是构造函数
function Fun(){console.log(this)} var f1= Fun() //调用函数,并把返回值赋值给f1 var f2=new Fun() //创建一个对象,并把对象返回给f2
构造函数执行流程
1.立即创建一个新对象
2.将对象设置为this
3.执行函数内代码
4.将新建对象返回
为构造函数添加属性
function Fun(){this.name='tom'} var f2=new Fun() console.log(f2.name)
共享函数
//定义一个公用函数 function k() { console.log('hello' + this.name) } function fun(n) { this.name = n this.k = k } var f1=new fun('li') var f2=new fun('tom') console.log(f1.name) console.log(f2.name)
如果构造函数有返回值
1.当返回值是对象类型时,该对象作为整个表达式的值返回,this被丢弃
2.当返回值是值类型时,值类型被忽略,仍然返回this
函数上下文