引用数据类型
在之前的文章中,我们提及了与基本数据类型并列的引用数据类型,当时提到引用数据类型大致分为三类:数组Array,函数Function,对象Object。这篇文章将围绕这三者展开。
一.数组Array
1.数组概念
数组是数据的集合,如果你学过Python,那么用列表来形容Js中的数组更加贴切。存入数组的元素我们称为数组单元,每一个数组单元都配有一个下标,我们可以通过下标来索引数组中的值。
数组单元之间的类型可以相同,可以不同。
<script>
let a = ['Ashto', 'Gravin', 'Stevein', 123, true];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
}
</script>
看完代码,你应该学会了数组的创建方式,数组单元间的类型没有要求的特性 和遍历数组的方式了,遍历数组的过程是通过数组单元下标从0开始依次增大的特性来实现的。
2.数组操作
操作数组,实质上用四个字概括:增删改查
查与改
查我们只需要通过数组单元的下标进行索引就可以了,改变数组单元同理,我们只需要将值赋值给数组单元的下标位置就可以覆盖原有数据了。
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9];//创建数组
console.log(a[0]);//输出数组第一个元素
a[0] = 11;//将数组第一个元素改成11
console.log(a[0]);
增与删
添加数组元素:arr.push(new_element)或者arr.unshift(new_element)
push方法可以在数组最后添加一个或多个元素,unshift可以在数组首部添加一个或多个元素。
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9];//创建数组
a.push(11, 22, 33);//在数组尾部添加11,22,33
a.unshift(11, 22, 33)//在数组首部添加11,22,33
console.log(a);
删除数组元素:arr.pop()或者arr.shift()
pop方法删除掉数组的最后一个元素并返回这个元素,shift方法删除数组第一个元素并返回这个元素 。
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
last = a.pop();
first = a.shift();
console.log(a);
console.log(last);
console.log(first);
splice方法
说明:可以从指定位置删除或者增加的数组元素,注意它修改原数组
splice(start,deleteCount, item1, item2...)
1 . start 起始位置:
● 指定修改的开始位置(从0计数)
1 . deleteCount 删除个数:
● 表示要移除的数组元素的个数
● 可选的。如果省略则默认从指定的起始位置删除到最后
1 . item1, item2...● 新增的元素
二,函数Function
1.函数概念
函数就是把具有联系的代码封装在一起,方便后续直接使用,比如求和函数,求阶乘函数。
声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分
function factorial(n) {
res = 1;
for (let i = 1; i <= n; i++) {
res *= i;
}
return res;
}//定义了一个阶乘函数
a = factorial(5);
console.log(a);//返回120
观察这个阶乘函数,它包含function关键词,函数名(factorial),形式参数(n),函数体(大括号内的所有代码),返回值(这里是res,不过一些函数可以没有返回值) 。
调用函数的方式为 函数名(实际参数)就可以了。
形参:声明函数时小括号里的叫形参(形式上的参数)
实参:调用函数时小括号里的叫实参(实际上的参数)
现在,你应该对函数有一定了解了。
接下来,我们讨论一些特殊情况:
如果形参大于实参数量:
形参大于实参,在函数调用时会进行自动补全,缺失的实参会以undefined的类型传入函数,结果一般为NaN。
如果实参大于形参数量:
实参大于形参,在函数调用时会忽视掉多出来的实参。
2.逻辑中断
逻辑中断: 存在于逻辑运算符 && 和 || 中,左边如果满足一定条件会中断代码执行,也称为逻辑短路
false && anything // 逻辑与左边false则中断,如果左边为true,则返回右边代码的值
true || anything // 逻辑或左边true则中断,如果左边为false,则返回右边代码的值
<script>
// 逻辑中断 && ||
// 1. 逻辑与中断:如果左边为假,则中断,如果左边为真,则返回右边的值
console.log(false && 1 + 2) // false
console.log(0 && 1 + 2) // 0
console.log('' && 1 + 2) // ''
console.log(undefined && 1 + 2) // undefined
console.log(true && 1 + 2) // 3 此处不会发生逻辑中断
console.log(1 && 1 + 2) // 3 此处不会发生逻辑中断
// 2. 逻辑或中断,如果左侧为真,则中断,如果左侧为假,则返回右边的值
console.log(true || 1 + 2) // true 发生了中断
console.log(1 || 1 + 2) // 1 发生了中断
console.log(false || 1 + 2) // 3 此处不会发生逻辑中断
// 3. 使用场景
// function sum(x, y) {
// return x + y
// }
// console.log(sum(1, 2)) // 3
// console.log(sum()) // NaN
function sum(x, y) { // x = undefined
// x = undefined || 0
// x = 1 || 0
x = x || 0
y = y || 0
return x + y
}
console.log(sum()) // 0
console.log(sum(1, 2)) // 3
</script>
3.其他知识
函数默认参数
当实参数量小于形参时,默认参数会起作用来补全参数值。
function factorial(n = 1) {
res = 1;
for (let i = 1; i <= n; i++) {
res *= i;
}
return res;
}//定义了一个阶乘函数
a = factorial();//不输入参数,使用函数参数的默认值
console.log(a);//返回结果为1
默认参数是我们提前预定好的,当实参存在时,那么实参覆盖默认值,否则使用默认值,如果没有默认值,则按undefined类型数据补全。
作用域
全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
处于全局作用域内的变量,称为全局变量
局部作用域
1 . 函数作用域。作用于函数内的代码环境
2 . 块级作用域。{ } 大括号内部
处于局部作用域内的变量称为局部变量
注意:
1 . 如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
2 . 但是有一种情况,函数内部的形参可以看做是局部变量。
函数表达式
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式。
// 声明
let fn = function() {
console.log('函数表达式')
}
// 调用
fn()
总结:
1 . 其实函数也是一种数据类型
2 . 函数表达式必须先定义,后使用
3 . 函数的形参和实参使用跟具名函数一致
三,对象Object
1.对象概念
对象(Object):JavaScript里的一种数据类型(引用类型),也是用于存储数据的
好处:可以用来详细的描述某个事物,是用键值对形式存储语义更明了
特点:对象数据是无序的,数组有序的
如果你学过面向对象类型的语言,那么这个引用类型应该会更好的理解。通常我们描述一个对象会会从它的属性和动作行为(方法)来描述,属性都是成对出现的,是类似字典的形式存在对象中的,方法更像是函数,但这些函数可以通过这个对象来调用,且一般和对象有关。
2.属性
对象属性
数据描述性的信息称为属性,如人的姓名、身高、年龄、性别等,一般是名词性的。
1 . 属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
2 . 多个属性之间使用英文 , 分隔
3 . 属性就是依附在对象上的变量(对象外是变量,对象内是属性)
let me = {
name: 'Ashto',
age: 19,
gender: 'Male',
occupation: 'Computer Engineer',
}
console.log(me);
console.log(me.age);
console.log(me.gender);
console.log(me.name);
3.方法
方法和属性类似,都是通过键值对来匹配关系,比如walk:walk();和属性非常相似,只不过属性键值的值是基本数据类型,而方法的键值的值是函数。
let me = {
name: 'Ashto',
age: 19,
gender: 'Male',
occupation: 'Computer Engineer',
study: function () {
console.log(this.name + 'is studying hard....');
},
}
console.log(me);
console.log(me.age);
console.log(me.gender);
console.log(me.name);
me.study();
看到这里,我们发现js的对象似乎和字典类型十分相似(键值对),所以我们是否可以用字典的形式操作对象呢?
答案是可以的,我们即可以用object.attribute来访问对象属性,还可以用object[key]来访问对象属性,同理,我们可以通过object.newattribute = value来创建键值对,也可以用object['key'] = value来创建键值对。删除对象属性直接使用delete关键词就行。
let me = {
name: 'Ashto',
age: 19,
gender: 'Male',
occupation: 'Computer Engineer',
study: function () {
console.log(this.name + 'is studying hard....');
},
}
me.study();
me['hobby'] = 'basketball';
console.log(me);
4.遍历对象
之前,我们遍历都是通过下标来访问数据的,但是对象它没有下标,这条方法就行不通了。
所以我们要利用 for in 遍历对象
语法:
for (let 变量 in 对象) {
console.log(变量) // 属性名
console.log(对象[变量]) // 属性值
}
1 . for in语法中的 k 是一个变量, 在循环的过程中依次代表对象的属性名
2 . 由于 k 是变量, 所以必须使用 [ ] 语法解析
3 . 一定记住: k 是获得对象的属性名, 对象名[k] 是获得 属性值
4 . 一般不用这种方式遍历数组、主要是用来遍历对象
<script>
// 遍历对象
let pig = {
sex: '女',
age: 4,
uname: '佩奇',
weight: 12.6,
}
// for (let key in pig) {
// console.log(key) // key 是属性
// console.log(pig[key]) // 对象[变量] 是值
// }
for (let key in pig) {
console.log(key) // key 是属性 对象.属性
// console.log(pig.key) // pig.key undefined 因为key是个变量不是属性
// key 'sex' 'age' 对象[key] 对象['sex'] 对象['age']
console.log(pig[key])
}
// 注意:数组遍历用传统for, for in 主要用来遍历对象
let arr = ['red', 'green', 'pink']
for (let k in arr) {
console.log(k)// 得到字符串类型的索引号
}
</script>
5.内置对象
<1>Math对象
<script>
// 内置对象Math
// 1. PI 属性 圆周率
console.log(Math.PI)
// 2. max 方法 找最大值
console.log(Math.max(8, 4, 2)) // 8
// 3. min 方法 找最小值
console.log(Math.min(8, 4, 2)) // 2
// 4. abs 方法 取绝对值
console.log(Math.abs(-1)) // 1
// 5. ceil 方法 向上取整 ceil 天花板 往大了取
console.log(Math.ceil(1.1)) // 2
console.log(Math.ceil(1.5)) // 2
console.log(Math.ceil(1.8)) // 2
console.log(Math.ceil(-1.1)) // -1
console.log(Math.ceil(-1.5)) // -1
console.log(Math.ceil(-1.8)) // -1
// 6. floor 方法 向下取整 floor 地板 往小了取
console.log(Math.floor(1.1)) // 1
console.log(Math.floor(1.5)) // 1
console.log(Math.floor(1.8)) // 1
console.log(Math.floor(-1.1)) // -2
console.log(Math.floor(-1.5)) // -2
console.log(Math.floor(-1.8)) // -2
// 7. round 方法 四舍五入取整
console.log(Math.round(1.1)) // 1
console.log(Math.round(1.5)) // 2
console.log(Math.round(1.8)) // 2
console.log(Math.round(-1.1)) // -1
console.log(Math.round(-1.8)) // -2
console.log(Math.round(-1.5)) // -1
</script>
<2>Random对象
<script>
// 1. Math随机数 Math.random()
// 1.1 随机的小数 0 ~1 之间
// 1.2 能取到0,但是取不到1 [0, 1)
// console.log(Math.random())
// 2. 取 0 ~ 10 之间的一个随机整数
// Math.random() * (10 + 1)
// (0 ~ 0.99999) * 11
// 0 ~ 10.99999
// Math.floor(Math.random() * (10 + 1))
// console.log(Math.floor(Math.random() * (10 + 1)))
// 3. 取 5 ~ 15 之间的一个随机整数
// Math.floor(Math.random() * (10 + 1)) 0 ~ 10
// Math.floor(Math.random() * (10 + 1)) + 5 5 ~ 15
// console.log(Math.floor(Math.random() * (10 + 1)) + 5)
// 4. 取 n ~ m 之间的一个随机整数 4 ~ 12
// Math.floor(Math.random() * (差值 + 1)) + 最小值
console.log(Math.floor(Math.random() * (8 + 1)) + 4)
</script>
总结:以上的内置对象使用频率还是挺高的,最好都有点印象,可以提升效率。
创作不易, 点点小赞,鼓励一下~