文章目录
函数
基础知识
函数的定义
function demo(){
//code...
}
const square = function(number) { return number * number; };
JS不支持函数的重载,后面写的会覆盖前面的。
function a(a,b,c){}//被覆盖了
function a(a,b){}
console.log(a);//f a(a,b){}
与其他语言中的函数一样,js中的函数遇到return语句就停止执行了,也就是说,return语句之后的语句都不会被执行。
如果一个函数没有return语句,那么这个函数默认返回undefined
函数表达式/标签函数
虽然上面的函数声明在语法上是一个语句,但函数也可以由函数表达式创建。这样的函数可以是匿名的;
const square = function(number) { return number * number; };
var x = square(4); // x gets the value 16
如果这样的函数用于字面量字符串:
用于字面量字符串时,有如下规定:
传入字面量字符串时,需要用反引号将参数包围,
如functionname `parameter`
标签函数的第一个参数是 传入参数去掉插入量剩下的字符串,
let sum = (strs, a, b) => {
console.log(strs); //[ '', ' + ', ' = ' ] 所有字符串字面量组成的数组
console.log(a); //85 插值
console.log(b); //100 插值
}
let a = 85;
let b = 100;
sum `${a} + ${b} = `;
剩余参数(重点)
剩余参数用于给函数传递不确定个数的参数,它实现的形式是数组,所以可以使用数组的方法。
对于一个函数来说,只能接受一个剩余参数变量,如果这个函数有多个变量,那么剩余参数必须是最后一个变量。
function add(a,b,c,...args){
//这是符合语法规则的
}
```js
```js
function add(...args, ...vals){
//这是不符合语法规则的
}
function demo(...args,a){
//这也是不符合语法规则的
}
…args和args的区别
function demo(...args){
console,log(...args);
//...args输出的是字符串 ‘1 2 3 4’
console.log(args);
//args输出的是array对象
}
Argument对象
arguments
是一个对应于传递给函数的参数的类数组对象。
每一个函数都会有这个数组对象,这个对象记录了函数接收的所有参数。
因为它的原型是Objecter而不是Array,所以它不是一个真正的数组,故称“类数组对象”,所以不能使用数组的方法。
用Arguments参数模拟函数重载
由于js中是没有重载这一概念的,如果要实现重载的时候,可以使用argument参数进行模拟。
原理:用if判断参数的个数,然后执行不同的代码;
function demo(){
if(argument.length === 1){
console.log(argument[0]);
}else if(argument.length === 2){
console.log(argument[0]+argument[1]);
}
/*....*/
}
demo(1); //1
demo(1,2) //3
Arguments对象中的callee与caller
callee是arguements对象中的一个属性,用于返回当前函数体正在执行的函数。
但在ES5的严格模式下,这两个属性已经被废除了,即使没有使用严格模式,这一属性也有其他的替代方法。
并且这两个属性会影响后续开发的优化。因此不推荐使用。
Arguments 与 剩余参数
剩余参数的表型形式是数组,所以它可以使用各种数组方法。
function multi(...a){
console.log(a); //Array(5) [1, 6, 9, 7, 6]
return a.reduce((p,c)=>(p*c));
}
multi(1,6,9,7,6);
function add(...adder) {
console.log(arguments);//Argument(4) [1,2,3,1]
return adder.reduce((p, c) => (p * c ))
}
add(1, 2, 3, 1);
Arguments参数可变性
arguments的参数是可以设置的,但是并不会影响函数的结果。
function multi(...a){
arguments[0]=6;
console.log(arguments);//Argument(2) [6,6] 发生了改变
// arguments[0];
return a.reduce((p,c)=>(p*c));
}
multi(1,6);//仍然是6
Arguments性能问题
对参数使用slice会阻止某些JavaScript引擎中的优化 (比如 V8 - 更多信息)。如果你关心性能,尝试通过遍历arguments对象来构造一个新的数组。另一种方法是使用被忽视的Array构造函数作为一个函数:
var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
详情请戳:https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
匿名函数
匿名函数顾名思义就是没有名字的函数。
var arr = [1,2,3];
arr.map((cur)=>(cur*2));
(cur)=>(cur*2)
就是一个匿名箭头函数
箭头函数
箭头函数是匿名函数的一种,他能让你的函数写的更简洁,更优雅。
let fn =()=>{//coding}
这样的函数常作为callback函数回调使用,如array的reduce、map函数都要求传入一个callback function作为参数。
let arr = [1,2,3,4,5,6];
arr.
箭头函数没有自己的this指针,所以箭头函数内使用的this指针默认继承父作用域的this指针,给出证明如下:
var a =0;
function foo() {
var a =50;
let show = ()=> {
var a = 55;
console.log(this.a);
}
show();
}
let obj={
a:666,
}
foo();//输出:0
箭头函数的this继承父作用域foo(),而这个作用域是定义在全局windows下的,所以foo作用域内的this指针指向全局windows,故箭头函数内的指针也指向全局windows。
如果此时用call方法改变foo函数的this指针指向。那么箭头函数内的this指针指向也会发生变化,由此可以证明:箭头函数内的this指针指向继承父作用域的this指针指向。
foo.call(obj);//把foo函数的this指向obj
//输出:666
可以看到,我们修改了foo内的this指向,导致了箭头函数show的输出的a变成了obj里面的a属性。
由此可以证明,箭头函数内的this指向继承父作用域,且随着父作用域的this指向改变而改变
IFEE 立即执行函数
立即执行函数,顾名思义,在定义的时候就会被调用的函数就是立即执行函数。
立即执行函数时匿名函数的一种,它具有自己的作用域,因此可以避免污染全局。
立即执行函数如何定义呢?
立即执行函数:(function(){function body})(parameter);
(function(){
//coding...
})();
(function(){}());
//其他定义
!function(){}();
~function(){}();
+function(){}();
void function(){}();
-function(){}();
避免污染全局的一个例子
一些变量只需要使用一次,之后便不会再调用了,这样的变量适合放在立即执行函数中去操作。
(function(){
var [year,month,day]=[2022,3,25];
/*通过一些代码让获取日期信息,这里直接进行赋值*/
document.body.innerHTML=`现在时间是${year}年${month}月${day}日`}());
这样一来,year、month、day这些变量名就不会跑到全局区域。