/**
* 顺带一提运算符
* + - * / 加减乘除
* % 取余 (5 % 2 结果为 1)
*
* = 赋值运算符,把右边的值给左边,这玩意儿可不是等于
*
* 逻辑运算符(运用在条件判断时)
* == 近似等 ("1" == 1 为true,虽然一个字符一个数值,但近似相等)
* === 等于 (类型相同且值相同 "1" === 1 为false)
* != 近似不等
* !== 不等
* > < >= <= 大于 小于 大于等于 小于等于
* || 或者
* && 且
* ! 非
*
* 位运算符 硬核且90%的程序不用,先不讲
*/
/**
* 顺带一提条件语句
* 都不需要解释,你肯定能看懂
*/
let a1 = 3
let a2 = 2
if(a1 > a2) {
console.log("a1 > a2")
}else if(a1 < a2) {
console.log("a1 < a2")
}else {
console.log("a1 === a2")
}
/**
* 一些常用的条件达成形式
* a //a为真
* !a //a为假
* a || b //一个为真
* a && b //a b都为真
*/
let a3 = 4
//a1 > a2 并且 a1 < a3
if((a1 > a2) && (a1 < a3)) {
//code
}
//等价于 a1 >= a2
if(!(a1 < a2)) {
//code
}
//三木(三目)运算符 condition ? code1 : code2
//条件condition达成时执行code1 否则执行code2
let ret = 0
if(a1 > a2) {
ret = 1
}else {
ret = 2
}
//用三木运算符简写
ret = a1 > a2 ? 1 : 2
/**
* 好了开始正题!
*/
//之前说过,程序是为了偷懒,但之前的教学里只有使用循环的时候
//好像才有点偷懒的意思(循环结构里面的逻辑可以多次执行)
//现在介绍另一个可以偷懒的方式
//函数
//简单理解为一段代码有了简称,通过简称来调用这一整段代码而不需要每次都去写这么大一段代码
//函数定义
function add(a, b) {
let sum = a + b
return sum
}
//字面量function表示定义一个函数,这个函数的名称为add,这个函数有俩参数
//a 和 b, 花括号里面的内容为函数体,也就是函数执行的逻辑,这个花括号里面单独为一个作用域
//可以理解为这个函数自己的空间,在这里面声明的变量(参数也是变量)只能自己以及这个函数内部的函数
//才能访问
//return 后面的表示函数的返回值
//这个函数的意思就是计算a 和 b 的和 并返回
//调用
let num1 = 5
let num2 = 4
let num3 = add(num1, num2)
console.log(num3) //打印9
/**
* 很简单,数值变量num1为5,num2为4,我们传入函数add,那么函数的参数a为num1的值5,b为num2的值4
* sum = 5 + 4 返回sum并复制给num3,所以num3就等于函数里面sum的值,所以为9
*/
/**
* 函数的参数和返回值 名字不是必须的
* 这也是一种常用的声明函数的方式
* =右边使用函数字面量声明了一个没有名字的函数(匿名函数)
* 然后将这个匿名函数赋值给了变量add2,这不代表这个函数的名字为add2,二是变量add2为一个函数类型的变量
* 并且引用了这个匿名函数(通过add2调用这个匿名函数)
* 而且这个函数其实啥也没干,但并不影响它是一个函数
*/
const add2 = function() {
}
add2() //调用它无事发生
/**
* 函数嵌套
* 一个js脚本是按书写顺序一行行执行的,遇到函数执行就会进入函数(即进入了这个函数的作用域,在函数
* 内容也是一行行执行的,这个过程和之前并无区别,函数体的书写和脚本书写亦如此。所以你在函数里面
* 也能定义函数,也能调用其他函数
*/
const logHello = function() {
console.log("hello")
}
const fakeAdd = function(a, b) {
logHello() //调用外部的函数
//定义内部函数 这个函数只有内部才能访问噢,这是函数作用域自己的变量
const realAdd = function() {
return a + b
}
return realAdd()
}
console.log(fakeAdd(1, 2))
console.log("================分割线======================")
/**
* 闭包函数
* 这是函数作用域的一种奇妙用法
* 很多时候,为了安全,我们的函数或者接口(一种对外的功能,调用者提供规定的数据,接口返回其需要的数据
* )只需提供返回数据的可读性,而函数内部的变量是不能够让外部访问的,这就需要用到闭包
*/
/**
* 假如我们有一个函数需要实现计数的功能,每次执行这个函数计数+1,我们可能会这样实现
*/
let _count = 0
let counter = function() {
_count++ //_count = _count + 1 的意思
return _count
}
console.log(counter()) //1
console.log(counter()) //2
console.log(counter()) //3
/**
* 好像没问题,但如果我不小心修改到了_count
*/
_count = 0
console.log(counter()) //1
/**
* 是不是很不安全,因为协作编程时,外部的变量可能会被其他人不小心修改到
*/
/**
* 奇妙
*/
/**
* 定义了一个getCounter函数,声明了变量_count并赋值0,
* 这个函数返回了一个匿名函数!
*
*/
const getCounter = function() {
let _count = 0
// 这个匿名函数的内容为_count++并返回_count的值
//_count为外部函数的变量,所以外部函数的外部无法访问!
return function() {
_count++
return _count
}
}
//调用这个函数会返回内部函数,所以那个内部函数可以通过counter1调用了!
let counter1 = getCounter()
console.log("---------分割线-------------")
console.log(counter1()) //1
console.log(counter1()) //2
console.log(counter1()) //3
_count = 0 //这个_count并不是getCounter内部的那个_count噢
console.log(counter1()) //4
/**
* 相当安全
* 闭包可能有点绕,可以多想一想
* 其实函数也是一种引用类型,通过函数变量加()来执行
*/
/**
* 闭包虽然安全,但不能乱用,因为内部的变量无法再直接访问到(只能在函数执行时内部访问)
* 所以无法自动回收这些变量所占的空间,所以闭包开辟的内存空间会一直存在整个程序生命周期
* 滥用闭包会导致内存泄漏
*/
/**
* 课堂作业
* 基本:书写一个函数传入两个数值并返回大的那个数。
* 进阶:利用闭包实现,如果你传入的两个数值和上次传入的一样就直接返回结果
*/
/**
* 函数还有很多知识比如箭头函数,构造函数,对象方法等
* 这些后面讲面向对象编程时再讲!
* 面向对象编程真的是程序最有趣的地方,如果你准备好了
* 微信大声告诉我《我准备好了》
* 我将在下一期带你探索面向对象编程
*/
console