js--函数
函数声明
语法:function funName([参数1],[参数2]) {}
函数可以通过名称调用:funName()
参数是可选的,参数之间用逗号分隔。
function showMessage() {
console.log( 'Hello everyone!' );
}
showMessage()
// Hello everyone!
function handel(a, b) { console.log(a+'----'+b) }
handel(1, 2)
//1----2
变量
函数拥有单独的作用域。
函数内定义的变量只能在函数内可见。
function handle() {
var a = 1
let b = 2
console.log(a + '----' + b)
}
handle()
console.log(a + '----' + b)
// 1----2
// Uncaught ReferenceError: a is not defined
函数可以访问函数外的变量,也可以改变外部变量的值。
如果函数内定义的变量与外部的变量同名,优先使用内部的值。
let b = 3
let a = 1
function handle() {
let b = 2
console.log(a)
console.log(b)
}
handle()
// 1
// 2
参数
参数(函数传参)将任意数据传递给函数。
函数的参数分为形参和实参。
形参:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
实参:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
function handle(a, b) { //形参
console.log(a + '----' + b)
}
handle(1, 2) // 实参
// 1----2
默认值
如果为实参未提供,形参默认值为undefined。
function handle(a, b) {
console.log(a + '----' + b)
}
handle(1)
// 1----undefined
如果想设定默认值,可以在形参后用=指定。
默认值可以是复杂的表达式。只会在实参缺少参数或设置参数为undefined时才会被计算和分配。
function handle(a, b = '默认值', c = 1 + 2) {
console.log(a + '----' + b + '----' + c)
}
handle(1)
handle(1,0)
// 1----默认值----3
// 1----0----3
可以通过||或运算符设置默认值。
或运算符无法区别出0,false,null,undefined,NaN,设置这些值仍显示默认值
function handle(a, b) {
var b = b || 2
console.log(a + '----' + b)
}
handle(1)
handle(1,0)
// 1----2
// 1----2
其他方法: 空值合并运算符??和条件分支if。
arguments(严格模式不可用)
arguments是一个对应于传递给函数的参数的类数组对象。
arguments对象是所有(非箭头)函数中都可用的局部变量
arguments包含传递给函数的每个参数,第一个参数在索引0处,长度由实际参数个数决定.
实参没有对应得形参,也可以通过arguments[下标]访问到。
函数中的形参和实参是可以相互影响的。
function handle(a, b) { console.log(arguments)}
handle(1) // [1, callee: ƒ, Symbol(Symbol.iterator): ƒ]
handle(1, 2) //[1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
handle(1, 2, 3) // [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
---------------------------------------------------------------------
function handel(a, b) {
arguments[0] = 2
console.log(a)
b = 3
console.log(arguments[1])
}
handel(1, 2) // 2 3
在rest(剩余)参数,默认参数和解构赋值下,arguments对象中的值不会跟踪参数的值,只会更改arguments中对应的值,不会更改形参中对应的值,反之亦然。
function handel(a, b, ...c) {
arguments[0] = 22
console.log(a)
console.log(arguments[0])
b = 55
console.log(b)
console.log(arguments[1])
}
handel(1, 2, 3, 4) // 1 22 55 2
callee:(严格模式下不可用)
返回一个正在被执行函数的引用 。
function handel() { console.log(arguments.callee) }
handel()
// ƒ handel() { console.log(arguments.callee) }
返回值
函数可以使用renturn 将一个值返回到调用代码中作为结果。
function handle(a, b) {
return a + b
}
console.log(handle(1, 2)) //3
函数中可以出现多个return。
function handle(a, b) {
if (a === 1) {
return a + b
} else {
return a - b
}
}
console.log(handle(1, 2))
没有return或者只有return返回值为undefined
function handle(a, b) {
if (a === 1) {
return
}
}
console.log(handle(1, 2)) // undefined
console.log(handle(2, 2)) // undefined
return会导致函数立即退出,之后的代码不再执行。
function handle(a, b) {
return a + b
console.log(a + '----' + b)
}
console.log(handle(1, 2))
// 3
不要在 return 与返回值之间添加新行,js 默认会在 return 之后加上分号。
function handle(a, b) {
return
(a + b)
}
console.log(handle(1, 2)) //undefined
相当于
function handle(a, b) {
return;
(a + b)
}
如果我们想要将返回的表达式写成跨多行的形式,那么应该在
return的同一行开始写此表达式。或者至少按照如下的方式放上左括号:
函数表达式
一种创建函数的方式。
语法: let funName = function [函数名] () { };
函数被创建并像其他赋值一样,被明确分配给一个变量。
函数表达式结尾要加分号;
let handel = function name() {
console.log('函数表达式')
};
handel() //函数表达式
在代码块的结尾不需要加分号
;,像if { ... },for { },function f { }等语法结构后面都不用加。函数表达式是在语句内部的:
let sayHi = ...;,作为一个值。它不是代码块而是一个赋值语句。不管值是什么,都建议在语句末尾添加分号;。所以这里的分号与函数表达式本身没有任何关系,它只是用于终止语句。
函数声明 vs 函数表达式
函数表达式是在代码执行到达时被创建,并且仅从那一刻起可用。
在函数声明被定义之前,它就可以被调用。
严格模式下,当一个函数声明在一个代码块内时,它在该代码块内的任何位置都是可见的。但在代码块外不可见。
handel()
var handel = function name() {
console.log('函数表达式')
}
// Uncaught TypeError: handel is not a function
--------------------------------------------------------
handel()
function handel() {
console.log('函数声明')
}
// 函数声明
函数对象
在js中,函数是对象。
function handel(params) {}
console.log(Object.prototype.toString.call(handel)) 、
// [object Function]
function handel(params) {}
console.dir(handel)
// arguments: null
// caller: null
// length: 1
// name: "handel"
name属性:
函数声明的名字可以通过name来访问。
function handel(params) {}
console.dir(handel.name)
// handel
函数表达式的名字也可以通过name来访问。在赋值中,会根据上下文来推测一个
如果函数自己没有提供,name在被赋值时,会赋值变量的名称。
如果函数自己提供,name在被赋值时,会赋值函数的名称 。该函数名称只能在函数内部使用。
let handel = function () {
console.log(handel.name)
}
handel()
console.log(handel.name) //handel handel
-------------------------------------------------------
let handel = function fun() {
console.log(fun.name)
console.log(handel.name)
}
handel()
console.log(handel.name) // fun fun fun
console.log(fun.name) // Uncaught ReferenceError: fun is not defined
无法推测时,name显示为空。
let arr = [function () {}]
console.log(arr[0].name)
// ''
length属性
它返回函数形参的个数。但是rest(剩余)参数不参与计数。
function handel(a) { console.log(handel.length) }
function handel1(a, b) { console.log(handel1.length) }
function handel2(a, b, ...c) { console.log(handel2.length) }
handel(1, 2, 3, 4) //1
handel1(1, 2, 3, 4) //2
handel2(1, 2, 3, 4) // 2
自定义属性
我们也可以添加自己的属性。
function handel(a) {
console.log(handel.CustomProperties)
}
handel.CustomProperties = '自定义属性'
console.log(handel.CustomProperties) //自定义属性
handel() //自定义属性
caller:(严格模式下无法使用)
返回一个调用当前函数的引用 如果是由顶层调用的话,则返回null。
function handel() { console.log(handel.caller) }
function handel1() { handel() }
handel1()
handel()
// ƒ handel1(params) { handel() }
// null
自执行函数
一般使用:(function(){ })()或者 (function(){ }());
声明函数的结构花括弧后面不能有其他符号,但是函数表达式可以。
function handel(){ console.log('自执行') }()
// Uncaught SyntaxError: Unexpected token ')'
let handel = function handel() { console.log('自执行') }()
//自执行
要想立即执行,函数必须是函数表达式。
而在function前面加上!、()、+、-、=等运算符,都可以将函数声明转换成为函数表达式。
+function(){ console.log('自执行1');}(); //自执行1
-function(){ console.log('自执行2');}(); //自执行2
!function(){ console.log('自执行3');}(); //自执行3
(function(){ console.log('自执行4');})(); //自执行4
(function(){ console.log('自执行5');}()); //自执行5
new Function
new Function是一种创建函数的方式,但是很少用到。
语法:let func = new Function ([arg1, arg2, ...argN], functionBody);
new Function 允许我们将任意字符串变为函数。
写法:
new Function('a', 'b', 'return a + b'); // 基础语法
new Function('a,b', 'return a + b'); // 逗号分隔
new Function('a , b', 'return a + b'); // 逗号和空格分隔
new Function('console.log(1111)'); // 只有函数体
let handel = new Function('a', 'b', 'c', 'return a+b+c')
console.log(handel(1, 2, 3))
// 6
let handel = new Function('a,b,c', 'return a+b+c')
console.log(handel(1, 2, 3))
//6
let handel = new Function('a ,b ,c ', 'return a+b+c')
console.log(handel(1, 2, 3))
// 6
let handel = new Function('console.log(1111)')
console.log(handel())
// 1111
new Function 创建的函数无法访问外部变量,只能访问全局变量。
let x = 20
function handel() {
let x = 10
let func = new Function('console.log(x)')
func()
}
handel()
// 20
箭头函数
箭头函数是另一种创建函数的方式,比函数表达式更简洁。
写法
let func = (param1, param2, …, paramN) => { statements }
let func = (arg1, arg2, ...argN) => expression
第二种相当于 (param1, param2, …, paramN) =>{ return expression; }
当代码块只有一个语句时{}可以省略,多行必须加花括号。
没有参数 ,括号也要保留。
let handel = () => console.log('箭头函数')
handel()
// 箭头函数
参数只有一个时,括号是可选的。
let handel = a => console.log(a)
handel(1) // a
箭头函数在参数和箭头之间不能换行。
let handel = (a)
=> console.log(a)
handel(1)
// Uncaught SyntaxError: Unexpected token '=>'
特点:
没有单独的this
没有arguments
不能new
也没有 super。