函数基本定义
JS定义
- js是异步的单线程的脚本语言
- 脚本: 边解释边执行
- 单线程: 就是同一个时间只执行一个任务(不能并发)
- 异步: js是基于事件驱动的语言, 通过事件循环来完成
JS的引入方式
- 属性级: 事件属性,直接写到html的事件属性中
<button onclick="show(this)">Click me</button>
- 标签级:script标签,只能作用于当前页面
<script>
const btn = document.querySelector('button');
btn.addEventListener('click', show);
function show(ev) {
console.log(ev.target.innerHTML);
ev.target.style.background = 'lightskyblue';
}
</script>
- 文件引入:可多页面共享
<script src="js.js"></script>
变量和常量
变量
- 变量声明 关键字let
<script>
//一行声明并初始化赋值
let name = 'jack';
//声明未初始化赋值,默认值underfind
let name;
</script>
常量
- 常量用const声明,常量名一般用大写,常量不能修改和更新,所以声明时需要初始化赋值
<script>
const APP = '系统';
</script>
变量和常量的命名规则
- 只能字母,数字,下划线,$,且不能以数字开头
- 标识符是严格区分大小写的
- 命名规范:推荐使用小驼峰命名法
//1.蛇形,下划线
let user_name;
//小驼峰,从第二个单词开始首字母大写
let userName;
//大驼峰,所有单词的首字母大写
let UserName;
变量类型及数据转换
原始类型
- 数值: 整数和小数
let age = 20;
- 字符串
let name = 'jack';
- 布尔
let request = true;
- underfind 初始化未赋值默认为underfind
let name;
- null
let request = null;
引用类型
- 对象
let man = {
//属性,相当于变量
name = 'jack',
age = 20,
gander = 'man'
//方法,相当于函数
getName: function () {
// this表示当前的上下文,当前对象
return '我的名字:' + this.name;
}
}
- 数组
let arr = [1,2,3,4];
//获取第三个元素
console.log(arr[2]);
//添加元素
console.log((arr[4] = 99));
//修改元素
console.log((arr[0] = 100));
- 函数
function hello(a, b, c);
console.log(arguments);
//添加元素
hello.d = 'd';
数据转换
- 通常只有相同类型的数据在一起运算,它的结果才有意义
- “+”:字符串运算中表示连接,此时会自动的触发类型转换
//字符串'100'在运算的时候会转换成数值类型
console.log(100 + '100');
//输出
100100
类型匹配
- 只检查值,而不检查类型: ==
console.log(100 == '100');
//输出 true
- 严格匹配推荐日常使用:===
console.log(100 === '100');
//输出 false
函数提升与重写
- 函数声明提升
//调用可以写在函数声明前
name();
function name() {
console.log("我叫:jack");
}
- 函数可以被重写
//将函数赋值给一个常量
const sum = function (a, b) {
return a + b;
};
归并、展开
归并,存在于参数中
- 举例
function demo2(...arr) {
console.log(arr);
}
demo2(1, 2, 3, 4, 5);
- 用rest剩余参数封装加法函数
function add1(...arr) {
// console.log(arr);
let res = 0;
for (let num of arr) {
res += num;
}
console.log('计算结果:',res);
}
add1(1, 2, 3, 4, 5, 6, 7);
//输出
计算结果:28
展开,存在于调用结果中
- 举例
let arr = [1,2,3,4,5,6];
console.log(...arr);
- 函数返回值:默认是单值;如果要返回多值,用引用类型(对象、数组)
function demo5() {
return {
status: 1,
message: "成功",
};
}
let res = demo5();
console.log(res.status, res.message);
箭头函数
箭头函数分为胖箭头=>和瘦箭头->
- 当参数只有一个时,圆括号可以省略,如果没有参数,反而不能省
- 当有多个参数时, 圆括号必须要写
- 当有多条语句时,函数体的大括号不能省
- 如果函数体只有一条语句时,可以省略大括号
let name = 'jack';
let age = 18;
let gender = 'man';
let num;
//完全写法
function demo6() {
return [name, age, gender];
}
res = demo6();
console.log(res);
//用箭头函数简写,可以省略function 和return及{}
let demo6 = () => [name, age, gender];
res = demo6();
console.log(res);
//如果只有一个参数可以省略()
let demo6 = num => [name, age, gender];
res = demo6(num);
console.log(res);
高阶函数
回调函数
- 回调函数就是把函数作为另一个函数的参数使用
document.addEventListener("click", function () {
alert("Hello World~~");
});
偏函数
- 简化了声明时的参数声明,把一些参数交给子函数处理
let sum = function (a, b) {
return function (c, d) {
return a + b + c + d;
};
};
let f1 = sum(1, 2);
console.log(f1(3, 4));
柯里化
- 每一级函数只处理一个参数
sum = function (a) {
return function (b) {
return function (c) {
return function (d) {
return a + b + c + d;
};
};
};
};
// 简化了调用参数
let res = sum(10)(20)(30)(40);
console.log(res);
纯函数
- 完全独立于调用上下文,返回值只能受到传入的参数影响
//纯函数
function add(a, b) {
console.log(a + b);
}
add(1, 2);
//不是纯函数
function getDate() {
return Date.now();
}
console.log(getDate());
作用域与闭包
作用域
- 全局作用域:全局都可以调用
let name = "jack";
- 局部作用域:函数作用域
function name() {
//函数私有变量
let age = 18;
console.log("我叫:jack");
}
- 块作用域:
{
let name = 'Tom';
}
闭包
能够访问自由变量的函数,所以理论上讲,任何函数都是闭包
自由变量: 即不是函数参数变量也不是私有变量,存在于函数调用上下文中
let num = 100;
function add(a, b) {
// a,b: 参数变量
// t: 私有变量
let t = 0;
// num: 自由变量
return t + a + b + num;
}
- 私有变量可以作为另一个函数的自由变量
function f1() {
let a = 1;
// a 相对于f1是私有变量,但是相对于返回的匿名函数就是一个自由变量
return function () {
return a++;
};
}
//把函数赋给一个变量
let f2 = f1();
//输出f1的匿名函数
console.log(f2());
立即执行函数
- 立即执行:声明完直接调用
//函数用()包含起来,并把调用直接跟随在后边
(function sum(a, b) {
console.log(a + b);
})(1, 2);