`复杂数据分支
复杂数据都是 对象 封装的,但为了方便开发人员开发,还是进行归类
数组
概念:将多个/多组数据(通常数据类型相同)按照顺序排列统一储存
定义: 数组是一组有序数据集合
集合内可以放多个数据、不限制数据类型
可以手动修改数组长度
声明数组
/*
* 两种声明方式
*/
var arr = [1,2,3,4,5,6];
var aaa = new Array(1,2,3,4,5,6);
数组元素(组内元素)
在数组内的所有数据叫做数组元素
获取/修改指定元素
var arr = [1,2,true,flase,"hello world"];
/*
* 获取第三个元素
* 注意:顺序读取是从 0 开始
*/
console.log(arr[2]);
//true
/* 改变元素本身数据甚至是数据类型
*/
arr[2] = "js";
console.log(arr[2]);
//js
获取/修改数组长度
/*
* 数组类型Array自带记录变量length
* 如果不能理解,简单认为数组后面直接加 .length 就可以知道数组长度
*/
var arr1 = [1,2,3,4,5,6,7,8,9]
console.log(arr2.length());
// 拓展:获取数组最后一个元素(注意长度和顺序关系)
console.log(arr[arr.length-1]);
// 9
// 超出长度部分不会被定义
console.log(arr[arr.length-1])
//undefined
/*
* 数组长度不是固定的,可以进行手动修改长度
* 若比原来长,多出来部分全为 undefined
* 若比原来短,自动删除多出部分, 删除不可逆!!!
*/
var arr2 = [1,2,3,4,5,6];
arr2.length=12;
// 变长
console.log(arr2.length);
console.log(arr[10]);
//12
//undefined
arr2.length = 2;
// 变短
console.log(arr2.length);
console.log(arr[3]);
//2
//undefined
arr2.length = 6;
// 删除不可逆
console.log(arr2.length);
console.log(arr[3]);
//2
//undefined
注意事项:
/*
* 显示全部数组时,数组会从头读到尾(与长度有关)
* null、undefined不会影响
*/
var arr = [1,true,null,"hello",[2,3],undefined,12];
console.log(arr);
//Array(7) [ 1, true, null, "hello", (2) […], undefined, 12 ]
/*
* 将 length 改长后,多出来部分不会显示出来
*/
arr.length = 15
console.log(arr);
//Array(15) [ 1, true, null, "hello", (2) […], undefined, 12, <3 empty slots>, … ]
// <3 empty slots>,... 指超过3个多余的元素
组内遍历
概念:对数组内每一个元素进行访问
思路:利用循环语句
var arr = [1,2,3,4,5,6,7,8,9];
for (var i = 0; i < arr.length; i++){
//每访问每一个元素
console.log(arr[i]);
}
函数
概念:通过js封装技术,封装一段或者一系列代码,被封装的代码会作为一个整体,在执行时执行,不执行时等待
声明函数
// 声明函数表达式
var fun1 = function(/* 输入 */){
// 被封装的代码
}
// 关键字定义函数
function fun2(/* 输入 */){
// 被封装的代码
}
调用函数
函数调用方法很简单,只需要以 函数名(输入参数) 结构即可(声明中没有参数,调用时就不写参数)
没有调用次数限制
function fun1() {
console.log("hello world");
}
// 调用函数
fun()1;
//hello world
// 带参函数
function fun2(str) {
// str为输入的参数
console.log(str)
}
// 输入参数 "hell"并调用函数
fun2("hell");
// hell
函数参数
根据上面简单涉及介绍, 函数参数是指函数括号内的变量
var fun1 = function(str){
console.log("函数的参数为:"+str);
}
fun1("1234")
//该函数的参数为:1234
/*
* 多组参数时,用逗号隔开
*/
var fun2 = function(str1, str2, str3){
console.log("函数的参数为:"+str1+", "+str2+", "+str3);
}
fun2("hello","the","world");
//函数的参数为:hello, the, world
// 若参数没写完,则剩余参数统一定义为 undefined
fun2("hello world");
//函数的参数为:hello world, undefined, undefined
优点:封装好的函数只需要告诉开发人员传入怎样参数就可以执行,没必要了解内部结构
函数返回值
函数不光能接受数据,也能返回一个值,通过 return 关键字来返回一个值。
结构:
var sum = function (a, b) {
return a+b;
}
var c = sum(3,4);
console.log(c);
//7
// 可以将函数返回值作为实参使用
var d = sum(sum(5,6),c);
console.log(d);
//18
/*
* 在不写return或者只写 return 没返回值时,返回值默认为 undefined
*/
function fun1(){
return;
}
function fun2(){}
console.log(fun1());
//undefined
console.log(fun2());
//undefined
注意:
- return 是函数终止指令,函数读到 return 后会返回值并停止执行
function fun(count){
console.log("1");
console.log("2");
console.log("3");
return ;
console.log("4");
console.log("5");
console.log("6");
}
fun(0);
//1
//2
//3
// 读到return后,4,5,6都不会出现
函数的数据类型
函数数据类型是 Function,可以作为一种数据类型参与其他程序
function fun() {}
// 不加括号是函数,加括号是执行函数
console.log(typeof(fun);
//Function
function f(a) {
var b = 200;
return function(){
var c = 300;
return a+b+c;
}
}
//由于返回值为一个函数,所以说再加一对括号来执行返回函数
console.log(f(100)());
//600
arguments对象
函数内部都内置一个 arguments 对象,其内存储所有传递的实参。(可以将arguments当成一个数组)
// arguments接受全部参数
function fun(){
console.log(arguments);
console.log(arguments);
//甚至可以当数组那样去逐个遍历
for (var i=0; i<arguments.length; i++)
console.log(arguments);
}
fun(1,2,3,4,5,6,7,8,9);
//Arguments { 0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, … }
//9
//1
//2
//3
//4
//5
//6
//7
//8
//9
function sum(a,b) {
return a + b;
}
// 实参的个数可以与形参不同,但最少一个,最多多一个
console.log(sum(1));
//1
console.log(sum(1,2));
//3
console.log(sum(1,2,3));
//6
console.log(sum(1,2,3,4));
//Uncaught Error: 参数个数不能超过 3 个
// 可以通过输入参数数量来执行不同表达式
function func(a,b,c){
switch (arguments.length){
case 1:{
return a;
break;
}
case 2:{
return b;
break;
}
case 3:{
return c;
break;
}
default:{
break;
}
}
}
函数递归
函数内调用自身函数的方式,就是函数递归现象
// 0~n之和
function sum(n) {
if (n==0)
return 0;
else
return n+sum(n-1);
}
console.log(sum(100));
//5050
// 斐波那契数列 => 后面的一项数据是前两项数据之和
var num = [1,1]; // 定义数组,记录每组斐波那契数列,减少运算时间
function fibo(n) {
if (n===1||n===2){
return 1;
}else if(!isNaN(num[n])){
return num[n];
}
else{
num[n]=fibo(n-1)+fibo(n-2);
return num[n];
}
}
console.log(fibo(3));
//2
console.log(fibo(20));
//6765
全局变量和局部变量
全局变量:定义在全局内,全局内都可以访问;关闭浏览器才会被销毁
局部变量:定义在函数内,只能在函数内访问;函数执行完会自动销毁
作用域链
函数可以制造作用域结构,而函数内又可以制作新函数,这样能形成新的作用域
这种在函数中套函数的套娃操作称作作用域链
function f1(){
function f2(){
}
}
function f3(){
function f4(){
}
}
IIFE
全称:immediately-invoked function expression, 即时调用函数表达式,简称自调函数
自调函数意义在于编写完成后就自动执行
执行方法:末尾 + ()
// 声明函数表达式会可以立即执行
var fun1 = function(){
console.log(11);
}();
//11
// 关键字定义函数不能立即执行,要在函数外套上括号
(function(a){
console.log(a);
})(5);
//5
// 也可以使用 + 、 - 、 ! 让函数矮化成表达式
+ function fun() {
console.log(123);
}();
//123
- function fun() {
console.log(111);
}();
//111
!function fun() {
console.log(135);
}();
//135
对象
结构:
var obj = {
k1: v1,
k2: v2,
k3: v3
};
/*
* obj为对象,对象内可以存储多个数据以及数据类型
* k -> 对象内属性名
* v -> k变量对应的属性值,可以为简单类型数据、函数、对象
*/
这样的结构有点像数组,但其又与数组不同,比如说访问方式
var arr = [1,2,3,4];
var obj = {
k1: 1,
k2: 2,
K3: 3,
k4: 4
}
// 访问
// 数组是根据顺序位置访问
console.log(arr[2]);
// 对象是根据内部属性名进行访问
console.log(obj.k2);
console.log(obj["k2"]);
对象中的属性和方法
属性:对象中的变量,用于存储数据
方法:对象中的函数,用于执行命令
调用对象内部属性及方法
-
用对象的变量名打点调用某个属性名,得到属性值。
persion.name -
在对象内部用 this 打点调用属性名。this 替代对象。
this.name = name -
用对象的变量名后面加 [] 调用,[] 内部是字符串格式的属性名。
persion["name"] -
调用方法时,需要在方法名后加 () 执行。
persion.getName()
更改对象内部属性和方法
// 更改对象属性:访问属性再赋值
person.name = "张三";
// 新增一个属性以及属性值:使用点语法或者[]直接定义并赋值
person.age = 19;// 点语法
persion["height"]= 178; // []方法
// 删除一某条属性
delete person.height;
对象的综合使用
创建对象
- Object() 是一种初始化对象的构造函数,一般以
var obj = new Object();方式创建
var person = new Object();
person.name = "张三";
person.age = 20;
person.sex = "男";
- 如果创建对象很多,属性都一样,可以通过一个函数来进行统一封装,简化代码
function createPersion(name, age, job) {
var person = new Object();
person.name = name;
person.age = age;
person["sex"] = sex;
person.test = function () {
console.log("test");
};
return person;
}
- 或者自定义构造函数
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
this.test = function () {
console.log("test");
}
}
// 创建对象
var p1 = new Person("张三", 20, "男");
遍历对象
for in
for in 循环专门用于遍历对象,内部定义一个变量k ,每次循环都是从第一个属性开始访问,一直访问到最后一个属性终止
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
var p1 = new Person("张三", 20, "男");
for (var k in p1)
console.log("属性 "+ k +" 的属性值为: "+p1[k]);
/*
* 最好使用 p1[k] 方式访问
* 毕竟 p1 内没有 k 属性
*/
简单和复杂类型区别
简单类型:值类型,基本数据类型,存储时, 变量自身值 = 内存存储值
复杂类型:引用类型,存储时, 变量自身值 = 内存地址值
存储区别:堆和栈
堆栈空间分配区别:
栈:由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等
堆:存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收
简单类型的内存存储
存储地方为 堆, 赋值时是将内部值赋值给另一个
复杂类型的内存存储
如果将复杂类型的数据赋值给一个变量,复杂类型的数据会在内存中创建一个原型,而变量 中存储的是指向对象的一个地址,如果将变量赋值给另一个变量,相当于将地址复制一份给 了新的变量,两个变量的地址相同,指向的是同一个原型,不论通过哪个地址更改了原型, 都是在原型上发生的更改,两个变量下次访问时,都会发生变化
内置对象
JavaScript内部自带的对象,开发人员可以直接使用内置对象部分属性或方法,便于开发
MDN
Mozilla 开发者网络(MDN),提供有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及 HTML5 应用的 API。
详细以后再来补。
Math内置对象
Math对象具有数学领域常用的函数属性和方法,便于我们进行数学计算
| 属性/方法 | 含义 |
|---|---|
| Math.PI | 圆周率,∏ |
| Math.random() | 生成随机数 |
| Math.floor() | 向下取整 |
| Math.ceil() | 向上取整 |
| Math.round() | 四舍五入式取整 |
| Math.abs() | 绝对值 |
| Math.max()/min() | 求最大值/最小值 |
| Math.sin()/cos() | 正弦/余弦 |
| Math.power() | 求指数次幂 |
| Math.sqrt() | 求平方根 |
Array内置对象
检测复杂数据类型
/* 检测某个实例对象是否属于某个对象类型
* 结构为: 变量 instanceof 数据类型
* 仅限于 复杂类型 判断
*/
console.log([1,2,3,4,5] instanceof Array);
//true
console.log({name:"zhangsan"} instanceof Array);
//false
console.log({} instanceof Object);
//true
console.log("hello" instanceof String);
//false
toString方法
将数组内所有元素转换成字符串输出
var num = [1,2,true,false,"hello",[4,5],undefined,null,function(){return 123;},{name:"张三"}];
console.log(num.toString());
//1,2,true,false,hello,4,5,,,function(){return 123;},[object Object]
常用方法
首、尾数据操作
| 方法名 | 说明 |
|---|---|
| unshift() | 数组开头添加一个或多个元素,并返回最后数组长度 |
| shift() | 删除数组第一个元素,并返回删除元素的值 |
| push() | 数组末尾添加一个或多个元素,并返回最后数组长度 |
| pop() | 删除数组末尾元素,并返回删除元素的值 |
合并
/* concat( 数组 )
* 将两个及以上数组合并成一个新的数组,其中括号内内容补充到原数组后面
*/
var num1 = [1,2,3,4,5];
var num2 = [6,7,8,9,10];
console.log(num1.concat(num2));
//[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
拆分
/* slice( start, end )
* 从顺序数第 start 开始一直到第 end 前为止(不包括 end)
* start、end 必须 同正负
同正时,代表顺数
同负时,代表倒数
* 拆分时对原数组无影响,不会改变原数组
*/
var arr = [1,2,3,4,5,6,7,8,9,10];
var arr1= arr.slice(2,7);
console.log(arr1);
//[ 3, 4, 5, 6, 7 ]
var arr2= arr.slice(-7,-2);
console.log(arr2);
//[ 4, 5, 6, 7, 8 ]
删除插入替换一条龙
// 核心方法: splice()
/* 删除写法: splice( start , deleteCount ); start为开始位置,deleteCount 为删除数量
* 返回删除数据
*/
var arr = [1,2,3,4,5,6,7,8,9,10];
// 被删除的内容
console.log(arr.splice(2,7));
//[ 3, 4, 5, 6, 7, 8, 9 ]
console.log(arr);
//[ 1, 2, 10 ]
/* 替换写法: splice( start, delectCount, Element1, Element2,...)
start为开始位置,deleteCount 为删除数量(或者是替换数量)
Element1、Element2...为替换内容
* 替换数量可以与Element数量不等
* 返回值依旧是删除数据(或者说是被替换的数据)
*/
arr = [1,2,3,4,5,6,7,8,9,10];
arr.splice(2,5,"三","四");
console.log(arr);
//[ 1, 2, "三", "四", 8, 9, 10 ]
/* 插入写法: splice( start, 0, Element1, Element2,...)
start为插入位置
Element1、Element2...为插入内容
* 返回值为 []
*/
arr = [1,2,3,4,5,6,7,8,9,10];
arr.splice(2,0,2.1,2.5);
console.log(arr);
//[ 1, 2, 2.1, 2.5, 3, 4, 5, 6, 7, 8, 9 ]
定位方法
/* 定位element第一次出现: indexOf( element )
* 返回值为第一次出现位置;找不到返回 -1
*/
var arr = [1,2,3,1,4,5,6,1,7,9,2];
console.log(arr.indexOf(1));
//0
console.log(arr.indexOf(11));
//-1
/* 定位element最后一次出现: indexOf( element )
* 返回值为最后一次出现位置;找不到返回 -1
*/
arr = [1,2,3,1,4,5,6,1,7,9,2];
console.log(arr.lastIndexOf(1));
//7
console.log(arr.lastIndexOf(11));
//-1
倒序
/* 将数组内全部元素顺序颠倒
* 会改变原来数组顺序
*/
var arr = [0,1,2,3,4,5,6,7,8];
console.log(arr.reverse());
//[ 8, 7, 6, 5, 4, 3, 2, 1, 0 ]
console.log(arr);
//[ 8, 7, 6, 5, 4, 3, 2, 1, 0 ]
排序
/* 按顺序对数组进行排序:sort()
* 默认按照字符编码顺序从小到大排列
*/
var arr = [1,2,3,4,5,6,7,8,9,10,20,30];
console.log(arr.sort());
//[ 1, 10, 2, 20, 3, 30, 4, 5, 6, 7, 8, 9 ]
/* 若想进行数值大小排序,必须添加 比较函数参数
*/
arr = [1,2,3,4,5,6,7,8,9,10,20,30];
arr.sort(function(a,b){
if (a < b) {
return -1; // a 排在 b 前
} else if (a > b) {
return 1; // a 排在 b 后
} else {
return 0; // a b 不换位置
}
});
console.log(arr);
转换成字符串
/* 将数组内所有元素通过字符串连接 join( "自定义字符串" )
* 返回值为: 元素+"自定义字符串"+下一个元素 ...
* 对数组无任何影响
*/
var arr = [1,2,3,4,5,6,7,8,9,10,20,30];
console.log(arr.join("**"));
//1**2**3**4**5**6**7**8**9**10**20**30
console.log(arr);
//[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30 ]
清空数组
var arr=[1,2,3,4,5,6,7,8];
// 方法很多,这里只是举例
arr = [];
arr.length=0;
arr.splice(0,arr.length);
String内置对象
为了方便对操作简单数据String,JavaScript提供String内置对象以便于对String进行操作
使用String内置方法时,会将字符串转换成String对象
var str = "零一二三四五六";
console.log(str.substring(2,5));
// 二三四
常用属性
字符串长度
// 长度:length
var str = "0123456789";
console.log(str.length);
//10
常用方法
定位指定位置的字符
/* charAt( num ): 字符串中第 num 处的字符
* 返回值 第num处的字符,若超过长度,则返回空字符 <empty string>
* 不会影响原字符串
*/
var str = "零一二三四五六七八九十";
console.log(str.charAt(3));
//三
console.log(str.charAt(15));
//<empty string>
console.log(str);
//"零一二三四五六七八九十"
查找某个字符串
/* indexOf(aim):查询 aim 第一次出现位置
* 返回值: >=0 出现位置 ; -1 没有找到
* 对原字符串无影响
*/
var str = "零一二三四五六七八九十二";
console.log(str.indexOf("二"));
//2
/* lastIndexOf(aim):查询 aim 最后一次出现位置
* 返回值: >=0 出现位置 ; -1 没有找到
* 对原字符串无影响
*/
console.log(str.lastIndexOf("二"));
//11
拼接字符串
/* concat(str):拼接 str
* 拼接一个及以上str
* 拼接位置在前一个末尾
*/
var str = "字符串:";
console.log(str.concat("一二三","哈哈哈"));
//字符串:一二三哈哈哈
分割字符串成数组
/* split( char ):通过 char 将字符串分割成多个数组元素
* 返回值为新的数组 Array
* 对原字符串无影响
*/
var str = "1,2,3,4,5,6,7";
var arr = str.split(",");
console.log(arr);
//[ "1", "2", "3", "4", "5", "6", "7" ]
全转换成大小写
// toLowerCase():全转换成小写
// toUpperCase():全转换成大写
// 对原字符串没影响
var str = "asdFGH";
console.log(str.toLowerCase());
//asdfgh
console.log(str.toUpperCase());
//ASDFGH
console.log(str);
//asdFGH
提取某段字符串
var str = "asdfghjkl";
/* 方法一: slice( start, end )
* 从 start 到 end前(不包括end)
* 正/负 顺序/倒序
*/
console.log(str.slice(2,4));
//df
console.log(str.slice(-5,-2));
//ghj
/* 方法二: substr( start, howmany )
* 从 start 开始,取值长度为 howmany(howmany必须为正数,若是省略便是取到末尾)
* 正/负 顺序/倒序
*/
console.log(str.substr(2,4));
//dfgh
console.log(str.substr(-6,4));
//fghj
/* 方法三: substring( start, end )
* 从 start 到 end前(不包括end)
* 只能取正数
*/
console.log(str.substring(2,7));
//dfghj