前端入门第六步:JavaScript 数组、对象、函数

221 阅读12分钟

`复杂数据分支

复杂数据都是 对象 封装的,但为了方便开发人员开发,还是进行归类

数组

概念:将多个/多组数据(通常数据类型相同)按照顺序排列统一储存

定义: 数组是一组有序数据集合

​ 集合内可以放多个数据、不限制数据类型

​ 可以手动修改数组长度

声明数组

/*
 * 两种声明方式
 */
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

注意

  1. 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