DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • html

  • css

  • javascript

    • js基础语法开篇
    • js基础语法之函数
      • 定义与调用
      • 局部与全局变量
      • 作用域
        • 函数内的代码块
        • if里的代码块
        • 闭包
        • 变量提升
        • 函数提升
    • BOM操作
    • DOM操作
    • js案例
  • jquery

  • UI库

  • 第一次学vue

  • 第二次学vue

  • 前端
  • javascript
DC
2023-10-13
目录

js基础语法之函数

# 定义与调用

无参 有参 带返回值 匿名 立即执行

// 1> 无参函数
function f1() {
  	console.log("无参函数!");
};
f1();

// 2> 有参数函数
function f2(a, b) {
  	console.log("有参函数!", a + b);
};
f2(10, 20);

// 3> 带返回值的函数
// js不能像python一样返回多个值..
// js只能返回一个值.(可将多个值放到数组或"字典 js中叫对象"中)
function f3() {
  	return [111, 222, 333];
};
f3();

// 4> 匿名函数
// 函数是一等公民!所以可以赋值给变量.
var f4 = function (a, b) {
  	console.log("匿名函数!", a + b);
}
f4(20, 30);

// 5> 立即执行函数
// 注意要用一个括号将函数包裹起来..
(function (a, b) {
  	console.log("立即执行函数!", a + b);
})(11, 22);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

内置的arguments对象
相当于将所有参数汇总到一个数组对象里面去了. 相当于python里的*args

function f2(a, b) {
    console.log(arguments);  // 内置的arguments对象
    console.log(arguments.length); // 2

    console.log(arguments[0], arguments[1]); // 10 20
    console.log(a, b); // 10 20 
};
f2(10, 20);
1
2
3
4
5
6
7
8

# 局部与全局变量

局部变量
     在JavaScript函数内部声明的变量(使用 var)是局部变量.
     所以只能在函数内部访问它(该变量的作用域是函数内部).

全局变量
     在 函数外 声明的变量是全局变量, 网页上的所有脚本和函数都能访问它
     在 函数内 不加var关键字声明的变量也是全局变量.

变量生存周期
     JavaScript变量的生命期从它们被声明的时就开始
局部变量会在函数运行以后被删除
全局变量会在页面关闭后被删除

Ps: ES6的语法 let关键字声明的变量只属于自己的{}花括号 -- 块级作用域!
(let 关键字要考虑浏览器兼容性问题..)


# 作用域

首先在函数内部查找变量, 找不到则到外层函数查找, 逐步找到最外层.
另外函数的作用域关系是在定义阶段就固定死的, 与调用位置无关. - 与python一样的!!

# 函数内的代码块

下方的这一段代码的语法跟python类似!

var x = 11; // 全局x
var a = "芜湖"

function test() {
    // 局部变量只能在局部访问得到
    var x = 22; // 局部x
    var y = 33; // 局部y
    // 在js和shell里不加关键字声明的变量会在全局
    z = 44; // 全局z
    console.log(x,y,a);
};
test() // 22 33 "芜湖"
// console.log(y) 报错 因为函数都已经运行完了.y变量被释放了..
console.log(x) // 11
console.log(z) // 44
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# if里的代码块

但凡涉及到子代码块的地方就需要讨论作用域啦!
除了函数,if for switch while都可以包含子代码块!

// 1> 默认情况下,if子代码块内声明变量的作用域是与if所在的位置保持一致的,即if在全局代码块里的变量就在全局,在函数里就局部
if (true) {
		// 因为if的位置在全局,所以m变量也属于全局
		var m = 666
}

function test() {
		// 因为if的位置在局部,所以n变量也属于局部
		if (true) {
				var n = 666
		}
}

// 2> 若想让if的子代码块有自己的作用域,用ES6的新语法 let关键字
// 即let声明的变量只属于自己的{}花括号
if (true) {
		let p = 666; // ★ 这个p变量在全局就访问不到了!!
}

/* 
下面几行代码. 一共有三层作用域.
var x = 11

function f() {
		var x = 22
		if (true) {
				let x = 33
		}
}
*/

for (var i = 0; i <= 3; i++) {}
console.log(i) // 4  

for (let j = 0; j <= 3; j++) {
		var b = 10
}
// console.log(j) 报错! for循环里用let关键字声明的变量不会污染全局作用域!!!
console.log(b) // 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 闭包

先看python代码的实现与解决.

my_list = []
for i in range(5):
    # 定义完f函数后,并没有运行函数体代码
    # 函数体里的i以定义的时候为准,局部没有i,向全局要i
    def f():
        print(i)

    my_list.append(f)

# 调用的时候,全局的i的值为4
my_list[0]()  # 4
my_list[1]()  # 4

# --------------------使用闭包解决

my_list = []
for i in range(5):
    def outer(x):
        def f():
            print(x)
            
        return f

    f = outer(i)
    my_list.append(f)

my_list[0]()  # 0
my_list[1]()  # 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

再看js代码的实现与解决.

var arr = []
// 循环了5次 0 1 2 3 4
for (var i = 0; i <= 4; i++) {
    var f = function () {
      console.log(i)
    }
    arr.push(f)
}
console.log(arr[0]()) // 5 最后一次循环 i++后i的值为5,5<=4不成立,结束循环
console.log(arr[0]()) // 5

// ----------- 解决方案,闭包

var arr = []
// 循环了5次 0 1 2 3 4
for (var i = 0; i <= 4; i++) {
    function outer(x) {
        // var x = i 写在这就写死了..
        var f = function () {
          	console.log(x)
        }
        return f
    }

    var f = outer(i)
    arr.push(f)
}
console.log(arr[0]()) // 0
console.log(arr[1]()) // 1

// ------ 在这里,用let关键字能实现上面闭包的效果
// let属于块级作用域 但let一定要注意浏览器兼容的问题.. 现目前不建议用.
var arr = []
for (let i = 0; i <= 4; i++) {
    var f = function () {
        console.log(i)
    }
    arr.push(f)
}
console.log(arr[0]()) // 0
console.log(arr[1]()) // 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

函数的作用域关系是在定义阶段就固定死的,与调用位置无关!

// 栗子1
var city = "BeiJing";
function f() {
    var city = "ShangHai";
    function inner() {
        var city = "ShenZhen";
        console.log(city);
    }
    inner();
}

f();  //输出结果是 ShenZhen


// 栗子2
var city = "BeiJing";
function Bar() {
    console.log(city);
}
function f() {
    var city = "ShangHai";
    return Bar;
}
var ret = f();
ret();  // 打印结果是 BeiJing


// 栗子3
var city = "BeiJing";
function f() {
    var city = "ShangHai";
    function inner() {
        console.log(city);
    }
    return inner;
}

var res = f();
res(); // 打印结果是 ShangHai
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 变量提升

先来看一段python代码.╮(╯▽╰)╭(我也是醉了..)

var1 = "hello"
var2 = 111
var3 = []
var4 = None

# 报错: 在赋值前引用局部变量'x'
# 报错可以这样解释:
#   py的模块代码不会预编译,但函数体内的代码会预编译.即模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道.它们在预编译(或者说是检查语法)的时候,就在当前的局部作用域找到了变量名,所以不会根据LEGB的顺序依次找变量..只会向当前的局部作用域里要变量啦. 但在调用此变量时,此变量还没有绑定到一个内存对象(没有定义和初始化,即没有赋值).报错.
# 标注【○】的报错 还可以从python在作用域里的赋值规则这个角度来解释:
# 	若这个变量存在,则对其绑定新的对象;若不存在,则将这次赋值视为对这个变量的定义
#		前者是局部变量,后者是全局变量..冲突了..
def f():
    # var1 = var1.upper() 报错 ○

    # print(var1) 报错
    # var1 = var1.upper()

    # print(var2) 报错
    # var2 = 222

    # var3 = var3.append(3) 报错 ○

    # print(var3) 报错
    # var3 = var3.append(3)
    
    # if var4 is None: 报错
    #     var4 = []
    
    # print(a) 报错
    # a = 555

    print(var1)
    var1.upper()

    print(var3)
    var3.append(3)


f()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

而js的代码就不会出现上方python的这些问题.
变量提升就是将所有的 变量声明语句 提升到变量自己作用域的最上面!代码还是一行行的依次运行.

1> 在全局作用域的变量提升

示例1:

console.log(a); // undefined
var a = "Hello World.";
console.log(a); // Hello World.

// ---- 上面这段代码等同于下面这段代码!

var a; // a变量的声明语句
console.log(a); // undefined -- a声明过但没赋值
a = "Hello World.";
console.log(a); // Hello World.
1
2
3
4
5
6
7
8
9
10

示例2:

var a = 10;
if (true) {
    console.log(a); // 10
    var a = 20;
    console.log(a) // 20
}
console.log(a); // 20
1
2
3
4
5
6
7

2> 在函数局部作用域里变量提升

示例1:

var x = 10;
function f() {
    console.log(x); // undefined
    var x = 20;
    console.log(x) // 20
}

// ---- 上面这段代码等同于下面这段代码!

var x = 10;
function f() {
    var x; // x变量的声明语句
    console.log(x);
    x = 20; // 给x变量赋值
    console.log(x)
}

f()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

示例2: 此例子函数体里未用到变量提升..

var x = 10;

function f() {
  	// 代码一行行的运行
    console.log(x); // 10 运行到这,全局的x值为10
    // f函数里没有x变量声明(无var关键字),所以这里这个x变量是属于全局的
    // 若全局没有就定义到全局;若全局有,则给全局的x变量重新赋值
  	// Ps:同一个变量只会声明一次,其他的会被忽略掉
    x = 20;
    console.log(x) // 20 运行到这,全局的x值为20
}

f()
1
2
3
4
5
6
7
8
9
10
11
12
13

# 函数提升

js中的函数跟python中的函数都是一等公民! 即定义函数跟定义变量是一样的,也有一个提升的效果..

只不过变量分为了两部分(声明+赋值),提升的是声明.
函数的提升是将 函数这一个整体 提升到所有代码最前面.
所以js中会很玄学,后面定义的函数,在前面也可以调用! python的函数必须先定义再调用!

注意: 若函数名和变量名一样,函数提升优先于变量提升..

console.log(f);
var f = "Hello!"
function f() {
    console.log("Hello World.")
}
console.log(f);

/*
ƒ f() {
    console.log("Hello World.")
}
Hello!
*/
1
2
3
4
5
6
7
8
9
10
11
12
13

js基础语法开篇
BOM操作

← js基础语法开篇 BOM操作→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式