JavaScript基础
# JavaScript 基础
JavaScript(通常缩写为 JS)是一种高级的、解释型的编程语言。JavaScript 是一门基于原型、头等函数的语言,是一门多范式的语言,它支持面向对象程序设计,命令式编程,以及函数式编程。
它被世界上的绝大多数网站所使用,也被世界主流浏览器(Chrome、IE、Firefox、Safari、Opera)支持。
JavaScript 是一种弱类型的动态类型语言。
# 数据类型
# 1. 分类
- 基本(值)类型
- String: 任意字符串
- Number: 任意的数字
- boolean: true/false
- undefined: undefined
- null: null
- 对象(引用)类型
- Object: 任意对象
- Function: 一种特别的对象(可以执行),判断其类型是不是 object 返回的为 true,即 Function 也是一种对象类型的数据
- Array: 一种特别的对象(数值下标, 内部数据是有序的,一般的对象中的数据是无序的),判断其类型是不是 object 返回的为 true,即 Array 也是一种对象类型的数据
# 2. 判断
typeof:
- 它可以判断: undefined/ 数值 / 字符串 / 布尔值 / function
- 它不能判断的:
- null 与 object 无法区分,因为判断 null 返回的也是 'object'
- object 与 array 也无法区分,因为返回的也都是 'object'
- 注意:typeof 的返回值是 数据类型的字符串表达
instanceof:
- 用来判断对象的具体类型
===
- 可以判断: undefined, null
# 3. undefined 与 null 的区别?
- undefined 代表定义未赋值
- null 定义并赋值了, 只是值为 null
let a;
console.log(a); // undefined
a = null;
console.log(a); // null
1
2
3
4
5
2
3
4
5
# 4. 什么时候给变量赋值为 null 呢?
初始赋值, 表明变量将要赋值为对象
结束前, 让对象成为垃圾对象(被垃圾回收器回收)
//起始
let b = null; // 初始赋值为null, 表明将要赋值为对象
//确定对象就赋值
b = ["hahaha", 123];
//最后
b = null; // 让b指向的对象成为垃圾对象(被垃圾回收器回收)
1
2
3
4
5
6
2
3
4
5
6
# 5. 严格区别变量类型与数据类型?
数据的类型
- 基本类型
- 对象类型
变量的类型(变量内存值的类型)
- 基本类型: 保存就是基本类型的数据
- 引用类型: 保存的是地址值
注意,变量本身是没有类型的,判断变量的类型实际上是判断变量的值的类型
# 什么是数据?
- 存储在内存中代表特定信息的'东东', 本质上是二进制的,0101...
- 数据的特点: 可传递, 可运算
- 一切皆数据(常说的万事万物皆对象其实有点偏差,毕竟不能说一个基础数据类型的数据是一个对象)
- 内存中所有操作的目标: 数据
- 常见的内存中的操作包括:
- 算术运算
- 逻辑运算
- 赋值操作
- 运行函数
# 什么是内存?
- 内存条通电后产生的可储存数据的空间(是临时的)
- 内存产生和死亡: 内存条(电路版)==>通电==>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失
- 一块小内存的 2 个数据
- 内部存储的数据
- 地址值
- 内存分类
- 栈: 全局变量/局部变量(标识对象的名称也是在栈空间中,例如函数名,数组名,对象名)
- 堆: 对象
# 什么是变量?
- 可变化的量, 由变量名和变量值组成
- 每个变量都对应的一块小内存, 变量名用来查找对应的内存, 变量值就是内存中保存的数据
# 内存,数据, 变量三者之间的关系
- 内存是用来存储数据的临时的空间
- 变量是内存的标识
# 赋值和内存的问题,即内存中到底保存的是什么?
问题: let a = xxx, a 内存中到底保存的是什么?
- xxx 是基本数据, 保存的就是这个基本数据值
- xxx 是对象, 保存的是对象的地址值
- xxx 是一个变量, 保存的 xxx 的内存内容(可能是基本数据, 也可能是地址值)
# 引用变量赋值的问题
关于引用变量赋值问题
- 2 个引用变量指向同一个对象, 通过一个变量修改对象内部数据, 另一个变量看到的也是修改之后的数据
- 2 个引用变量指向同一个对象, 让其中一个引用变量指向另一个对象, 另一引用变量依然指向前一个对象
<script type="text/javascript">
let obj1 = { name: "Tom" };
let obj2 = obj1;
obj2.age = 12;
console.log(obj1.age); // 12
function fn(obj) {
obj.name = "A";
}
fn(obj1);
console.log(obj2.name); //A
let a = { age: 12 };
let b = a;
a = { name: "BOB", age: 13 };
//此时将a重新赋值,即指向一个新的对象,此时b指向的对象依旧是以前的那个a指向的对象,即 b ={ age: 12 }
b.age = 14; //此时b对象的age属性改变了,但是此时的a对象的属性并不会因为b对象属性的改变而改变
console.log(b.age, a.name, a.age); // 14 BOB 13
function fn2(obj) {
// 此时修改的是引用变量的值,即让 obj 指向一个新的对象{ age: 15 },断开obj与a对象之间的指向,但是并不会影响a对象中的属性
// 虽然此时obj 指向了一个新的对象,但是在函数执行结束后就能释放了,就变成了一个垃圾对象,会被回收
obj = { age: 15 };
}
// 调用fn2这个函数,将a对象的内容拷贝一份赋值给fn2的形参obj,即此时fn2函数的形参指向的也是 a 对象,存储的也是 a 对象的地址值,
// 此时再在fn2函数中重新将obj 指向为其他的对象,只是将obj和原来的指向给断开了,并不会影响原来的对象的属性值, a 依旧指向以前的那个对象,它的属性值还是原来的,并没有被改变
fn2(a);
console.log(a.age); //13
</script>
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
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
# JS 调用函数时数据传递的问题
问题: 在 js 调用函数时传递变量参数时, 是值传递还是引用传递
- 理解 1: 都是值(基本/地址值)传递
- 理解 2: 可能是值传递, 也可能是引用传递(地址值)
<script type="text/javascript">
let a = 3;
function fn(a) {
a = a + 1;
}
// 此时传递的是 3 不是 a,即相当于是fn(3),在调用函数时,将函数中的形参 a 赋值为3,
// 此时函数内部操作的只是形参的数据,和原来的实参 a 没有任何关系,并不会影响原来的 a 的值
fn(a);
console.log(a);
function fn2(obj) {
// obj.name = "哈哈哈"; //此时修改是obj对象中的属性,并没有将形参obj和外部的实参obj的连接断开,所以会改变原来的obj对象的属性值
obj = { name: "去玩儿" }; //此时将形参obj和外部的实参obj的连接断开了,让其指向了新的对象{ name: "去玩儿" },此时并不会改变外部的原来的obj对象的属性值
console.log(obj.name); //此时输出的是内部的形参对象中的属性值,即函数内部的obj对象的name属性值,只要函数内部的形参的属性值改变,这个输出的结果就会被改变
}
let obj = { name: "Tom" };
// 此时传递是的obj对象的地址值,即调用fn2(obj)其实是相当于将原来对象的地址值赋值给了fn2的形参(局部变量obj),
fn2(obj);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# JS 引擎如何管理内存
- 1.内存生命周期
- 1.分配小内存空间, 得到它的使用权
- 2.存储数据, 可以反复进行操作
- 3.释放当前被分配的不使用的小内存空间
- 2.释放内存
- 局部变量: 函数执行完自动释放
- 对象: 成为垃圾对象==>垃圾回收器回收
- 全局变量在当前这一次运行中并不会被释放,因为释放了之后在其他地方就无法使用了
# JS 对象
# 1. 什么是对象?
- 多个数据的封装体。
- 用来保存多个数据的容器。
- 一个对象代表现实中的一个事物,是该事物在编程中的抽象。
# 2. 为什么要用对象?
- 便于对多个数据进行统一管理
# 3. 对象的组成
- 属性: 由属性名(字符串,只是为了简化写法可以不写双引号或者单引号)和属性值(可以是任意类型的数据)组成,代表现实事物的状态数据。
- 方法: 一种特别的属性(属性值是函数),代表现实事物的行为数据。
# 4. 如何访问对象内部数据?
- .属性名: 编码简单, 但有时不能用
- ['属性名']: 编码麻烦, 能通用
# 5. 什么时候必须使用['属性名']的方式?
- 1.属性名包含特殊字符:
- 或者空格
- 2.属性名不确定(属性名是一个变量,如果直接用 .属性名的方式来设置属性值,会导致设置的属性名是变量名,并不是变量的值)
<script type="text/javascript">
let p = {};
//1. 需求: 给p对象添加一个属性: content type: text/json
// p.content-type = 'text/json' //不能用,编辑器在代码保存的时候会直接报错
p["content-type"] = "text/json";
console.log(p["content-type"]);
//2. 属性名不确定
let propName = "myAge";
let value = 18;
// p.propName = value //不能用,此时表示的是p对象下的propName属性,并不是我们想要的自己设置的那个"myAge"
p[propName] = value;
console.log(p[propName]);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 函数
# 1. 什么是函数?
- 实现特定功能的 n 条语句的封装体
- 只有函数是可以执行的, 其它类型的数据都不能执行
# 2. 为什么要用函数?
- 提高代码复用
- 便于阅读交流
# 3. 如何定义函数?
- 函数声明
- 表达式
function fn1() {
//函数声明的方式定义函数
console.log("fn1()");
}
let fn2 = function () {
//表达式的方式定义函数
console.log("fn2()");
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4. 如何调用(执行)函数?
- test(): 直接调用
- obj.test(): 通过对象调用
- new test(): new 调用
- test.call/apply(obj): 临时让 test 成为 obj 的方法进行调用
# 5. 什么函数才是回调函数?
- 1.你定义的
- 2.你没有调
- 3.但最终它执行了(在某个时刻或某个条件下)
# 6. 常见的回调函数?
- dom 事件回调函数 ==>this 是发生事件的 dom 元素
- 定时器回调函数 ===>this 是 window
- ajax 请求回调函数
- 生命周期回调函数
# IIFE
# 1. 理解
IIFE : Immediately-Invoked Function Expression,立即调用函数表达式,定义时就会立即执行的 JavaScript 函数。
# 2. 作用
隐藏实现
不会污染外部(全局)命名空间,IIFE 中的匿名函数拥有 独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。
用它来编码 js 模块。
-【注意】如果将 IIFE 分配给一个变量,不是存储 IIFE 本身,而是存储 IIFE 执行后返回的结果。
# 3. 写法:
- 方式一:推荐使用 (function (){/_ code _/}())
- 方式二: (function (){/_ code _/})()
<script type="text/javascript">
//匿名函数自调用
// IIFE 中的匿名函数拥有 独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。
// 所以在这个函数中定义的变量能在外面再次定义,因为不属于同一个作用域。其内部定义的变量不会和外部的变量发生冲突
(function () {
let a = 3;
console.log(a + 3);
})();
let a = 4;
console.log(a);
(function () {
let a = 1;
function test() {
console.log(++a);
}
// 向外暴露一个全局函数
window.$ = function () {
return {
test: test,
};
};
})();
$().test(); // 1. $是一个函数 2. $执行后返回的是一个对象
</script>
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# JS 中的 this
# 1. this 是什么?
- 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是 window
- 所有函数内部都有一个变量 this
- 它的值是调用函数的当前对象
# 2. 如何确定 this 的值?
- test(): window,此时相当于是 window 来调用的 test()方法
- p.test(): p
- new test(): 新创建的对象
- p.call(obj): obj
完善页面 (opens new window)
上次更新: 2023-12-26 18:29:08