重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
为绥滨等地区用户提供了全套网页设计制作服务,及绥滨网站建设行业解决方案。主营业务为网站制作、成都网站建设、绥滨网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
目录
语法:...1
函数:...1
函数参数:...2
函数参数-普通参数:...2
函数参数-可变参数,rest parameters剩余参数:...3
arguments对象:...3
参数解构:...5
函数返回值:...5
作用域:...7
函数表达式:...9
函数、匿名函数、函数表达式的差异:...10
高阶函数:...11
箭头函数:...13
function 函数名(参数列表) {
函数体;
return 返回值;
}
例:
function add(x,y) { //没有逻辑
return x+y;
}
console.log(add(4,5)); //函数调用
一个参数占一个位置,支持默认参数;
js中没有py中的关键字传参,即缺省值不用像py那样往后放,建议默认参数写到后面;
js中只是作位置参数的对应;
js不限制位置参数的位置;
注:C、C++、java都是这样;
例:
const add = (x,y)=> x+y;
const add1 = (x,y=6)=> x+y;
const add2 = (x=8,y)=> x+y; //js中缺省值不用像py那样往后放(js中没有py中的关键字传参),建议像py那样默认参数写到后面;js只是作位置参数的对应;js不限制默认参数的位置;
console.log(add(4,5));
console.log(add(y=3,x=2));
console.log(add(aaa=1,bbb=2)); //V,相当于add(1,2),js中没有关键字传参,但是它的赋值表达式有值,aaa=1就是1
console.log(add()); //NaN,相当于add(undefined,undefined)
console.log(add1(4)); //相当于add(4,undefined)
console.log(add1(y=5,x=6));
console.log(add1()); //NaN,相当于add(undefined,6)
console.log(add2(2,2));
console.log(add(a1=5,(a2=6,a3=5))); //括号中表达式值为5
输出:
9
5
3
NaN
10
11
NaN
4
10
用...表示可变参数,py中用*收集多个参数;
例:
const add =function (...args) {
result =0;
for (let i in args) {
result +=args[i];
}
return result;
}
const sum = (...args)=> args;
console.log(add(3,6,9));
console.log(sum(2,4,6));
let arr = [1,2,3,4,5];
console.log(add(arr)); //X,这样返回的是字符串
console.log(typeof(add(arr)));
console.log(add(...arr)); //V,将arr解构
输出:
18
[ 2, 4, 6 ]
01,2,3,4,5
string
15
函数的所有参数会被保存在arguments的键值对字典对象中,py中的dict对应js中的对象;
ES6之前,arguments是唯一可变参数的实现;
ES6开始,不推荐,建议使用可变参数,arguements只是为兼容而保留;
例:
(function (p1, ...args) { //简写,函数定义+调用
console.log(p1);
console.log(args);
console.log(arguments);
for (let i of arguments)
console.log(i);
}) ('abc',1,3,5)
输出:
abc
[ 1, 3, 5 ]
{ '0': 'abc', '1': 1, '2': 3, '3': 5 }
abc
1
3
5
例:
((x,...args)=> { //简写,函数定义+调用
console.log(args);
console.log(x);
console.log(arguments);
}) (...[2,4,6,8,10])
输出:
[ 4, 6, 8, 10 ]
2
{ '0': {},
'1':
{ [Function: require]
resolve: { [Function: resolve] paths: [Function: paths] },
main:
Module {
id: '.',
exports: {},
parent: null,
filename: 'e:\\git_practice\\js\\node_833b816d371f0.tmp',
loaded: false,
children: [],
paths: [Array] },
extensions: { '.js': [Function], '.json': [Function], '.node': [Function] },
cache: { 'e:\git_practice\js\node_833b816d371f0.tmp': [Object] } },
'2':
Module {
id: '.',
exports: {},
parent: null,
filename: 'e:\\git_practice\\js\\node_833b816d371f0.tmp',
loaded: false,
children: [],
paths:
[ 'e:\\git_practice\\js\\node_modules',
'e:\\git_practice\\node_modules',
'e:\\node_modules' ] },
'3': 'e:\\git_practice\\js\\node_833b816d371f0.tmp',
'4': 'e:\\git_practice\\js' }
和py类似,使用...来解构;
另,js的参数解构,不需要解构后的值的个数和参数个数对应;
例:
const add = (x,y)=> {console.log(x,y);return x+y};
console.log(add(...[1,2]));
console.log(add(...[1,2,3,4,5]));
console.log(add(...[100]));
输出:
1 2
3
1 2
3
100 undefined
NaN
类C的语言,都有一个概念——表达式的值,类C语言都支持逗号表达式的值;
赋值表达式的值,是等号右边的值;
逗号表达式的值,是最后一个表达式的值;
js的函数返回值即使写的是多个,实际依然是单值;
另,py中,return 1,2,实质是返回一个tuple;
高级语言,基本都是多个入一个出;
例:
const add = (x,y)=> {return x,y};
console.log(add(4,100));
输出:
100
例:
const add = (x,y)=> {return x,y};
res =add(4.0,50);
console.log(res,typeof(res));
b = (x=5,y=6,true);
console.log(b);
a = (123,true,z='test');
console.log(a);
function c() {
return x=5,y=6,true,'ok'
}
console.log(c());
输出:
50 'number'
true
test
ok
例:
function a(obj) { //实际应用中,用来解决传参问题
obj.x =5;
return obj;
}
var o = {
x:100
}
console.log(a(o));
console.log(a(o).x);
输出:
{ x: 5 }
5
函数内定义的变量在函数外不可见;
var b = 200;,可提升声明,也可突破非函数的块作用域;
a = 100;,隐式声明不能提升声明,在严格模式下会报错,但可把变量隐式声明为全局变量,建议少用;
let c = 300;,不能提升声明,且不能突破任何块作用域,推荐使用;
例,函数中变量的作用域:
function test() {
a =100;
var b =200;
let c =300;
}
// console.log(a);
// console.log(b);
// console.log(c); //a,b,c均不可见
test();
console.log(a); //函数在调用后才会把a放到全局中
例,块作用域中变量的作用域:
"use strict"; //严格模式,此模式开启后,a = 100;不被允许;此句要么在文件首行,要么在函数首行
if (1) {
// a = 100; //X
var b =200;
let c =300;
}
// console.log(a);
console.log(b);
// console.log(c); //不可见
例:
function show(i,arg) {
console.log(i,arg);
}
x =500;
function fn() {
let z =400;
{
var o =100;
show(1,x);
t ='free'; //严格模式下会报错
let p =200;
}
var y =300;
show(2,z);
show(3,x);
show(4,o);
show(5,t);
// show(6,p); //let不能突破块作用域
{
show(7,y);
show(8,o);
show(9,t);
{
show(10,o);
show(11,t);
show(12,z);
}
}
}
fn();
// show(13,y);
show(14,t); //global,不要这样用
// show(15,o) //y,o函数外不可见
show(16,z); //var声明提升,此时还没有赋值
var z =10;
const m =2;
// m = 3; //常量不可以重新赋值
输出:
1 500
2 400
3 500
4 100
5 'free'
7 300
8 100
9 'free'
10 100
11 'free'
12 400
14 'free'
16 undefined
使用表达式来定义函数,表达式中的函数可以省略,如果这个函数名不省略,也只能用在此函数内部;
例,有名字的函数表达式:
const add =function _add(x,y) { //定义函数和常量时常用const,之后不可改;_add只能用在该函数内部
console.log(_add);
console.log(add);
return x+y;
}; //表达式后要有分号
console.log(add(4,5));
// console.log(_add(4,5)); //X
输出:
[Function: _add]
[Function: _add]
9
例,有名字的函数表达式:
const add =function fn(x,y) { //fn只能用在该函数内部
return x-y;
};
console.log(add(4,5));
// console.log(fn(4,5)); //X
例,匿名函数:
const add =function(x,y) {
console.log(add);
return x+y;
};
console.log(add(4,5));
例,递归:
const sum =function _sum(n) {
let result =0;
if (n==1)return 1;
return result +=n +_sum(--n);
};
console.log(sum(5));
输出:
15
函数 VS 匿名函数,本质上都一样,都是函数对象(变量指向一个函数对象),只不过函数有自己的标识符——函数名,匿名函数需要借助其它的标识符而已;
(函数、匿名函数) VS 函数表达式,区别在于:函数会声明提升(即调用可在声明之前),函数表达式不会(即调用必须在声明之后);
一般用,都是先声明再调用;
例:
console.log(show); //V,函数会声明提升
console.log(add); //X,函数表达式不会声明提升,即,const add不会上移,必须先声明再调用
const add =function(x,y) {
return x+y;
};
function show() {
console.log(add);
}
函数作为参数,或返回一个函数;
例:
function a() {
console.log('a func');
return function b() {
console.log('b func');
};
}
let func =a(); //返回值指向b函数的定义
func();
输出:
a func
b func
例:
function b() {
console.log('b func');
}
function a(fn) {
console.log('a func');
return fn;
}
let func =a(b);
func();
输出:
a func
b func
例,计数器:
let counter =function() {
let i =0;
// function inc() { //方式1
// return ++i;
// }
// return inc;
// return function() { //方式2,内部用不需要函数名
// return ++i;
// }
return ()=> ++i; //方式3,箭头函数
}
const c =counter();
console.log(c());
console.log(c());
console.log(c());
输出:
1
2
3
例,map函数:
function map(fn,arr) {
let newarr = [];
for (i in arr) {
newarr[i] =fn(arr[i]);
}
return newarr;
}
// let newarr = map(function (x) {return ++x}, [1,2,3,4,5]); //方式1
// let newarr = map((x) => {return ++x}, [1,2,3,4,5]); //方式2,若只留返回值(正确为++x),必须把{}和return一起脱掉,若为{++x}则没有返回值,返回的是[ undefined, undefined, undefined, undefined, undefined ]
let newarr =map((x)=> ++x, [1,2,3,4,5]); //方式3
console.log(newarr);
输出:
[ 2, 3, 4, 5, 6 ]
例,map函数,生成器实现:
var map =function* (fn,arr) { //生成器函数
for (i in arr)
yield fn(arr[i]);
};
let newarr =map(x => ++x, [1,2,3,4,5]); //生成器对象
for (i of newarr) //迭代
console.log(i);
输出:
2
3
4
5
6
是匿名函数,是一种更加精简的格式;
let newarr = map(x => ++x, [1,2,3,4,5]); //++x为return的值
箭头函数参数:
如果一个函数没有参数,使用();
如果只有一个参数,参数列表可省略小括号;
多个参数不能省略小括号,且使用逗号间隔;
箭头函数返回值:
若函数体部分有多行,就要用{},如果有返回值使用return;
若只有一行语句,可同时省略{}和return;
若只一条return语句,不能省略大括号,即有return关键字必须要有{},如let newarr = map(x => {return ++x},[1,2,3,4,5]);;
若只一条非return语句,加上{}则无返回值;
因此,记住最简形式x => x+2即可;
注:
windows.alert() //弹窗,browser对象,是全局对象,而js代码中的全局对象是在nodejs上;弹窗测试时用,现都用遮罩层
browser新版本支持生成器、箭头函数;
() => {},最简单的箭头函数,返回undefined;