所谓数组, 就是将多个元素 (通常是同一类型),按一定顺序排列放到一个集合中 , 那么这个多个元素的集合我们就称之为数组
特点 : 有顺序,有长度;
用途 : 存储大量的数据
总结 :
数组 : 多个元素的集合,这个集合有顺序,有长度。用途是存储大量的数据.
1)通过 构造函数 创建数组
var arr = new Array();//创建了一个空数组 var arr = new Array(1,2,3,4);//创建了一个数组,里面存放了4个数字 var arr = new Array(4);//创建了一个数组,长度为4,里面全是空值2)通过 数组字面量 创建数组
var arr1 = []; //创建一个空数组 var arr2 = [1, 2 , 3, 4]; //创建一个包含4个数值的数组,多个数组项以逗号隔开 var arr3 = [4]; // 创建一个数组,元素只有1个,,,元素是4数组的长度 : 跟字符串一样,,,数组有一个length 属性,, 指数组中存放的元素的个数 ;
var str1 = 'abc'; console.log(str1.length); var arr = [1,3,5,8]; console.log(arr.length);数组的下标 : 因为数组有序的,有序的就应该有自己的序号,,而这个序号就是每个元素对应的下标, 下标从0 开始 , 到 arr.length-1 结束
var arr = ["zs", "ls", "ww"]; arr[0];//下标0对应的值是zs arr[2];//下标2对应的值是ww var arr = ['zs','ls','ww']; // 0 1 2 // 下标 : 0 开始 arr.length-1 结束 长度:3 arr.length数组的取值 :
//格式:数组名[下标] //功能: 获取数组下标对应的那个值,如果下标不存在,则返回undefined。 // 下标范围 : 0 ~ arr.length-1 var arr = ["red", "green", "blue"]; // 打印 : arr[0];//red 打印 : arr[2];//blue 打印 : arr[3];//这个数组的最大下标为2,因此返回undefined数组的赋值 :
//格式:数组名[下标] = 值; //如果下标有对应的值,会把原来的值覆盖, var arr = ["red", "green", "blue"]; arr[0] = "yellow";//把red替换成了yellow // 如果下标不存在,会给数组新增一个元素。 arr[3] = "pink";//给数组新增加了一个pink的值 // 如果下标有跨度,,中间全是empty 不合法 // 特殊 : arr[arr.length] = 值 arr[arr.length] = '哈'; arr[arr.length] = '你妹';思考 : 如何给一个数组添加新的元素???? [重要]
arr[arr.length] = 值
arr.push(值)
遍历 : 对数组的每一个元素都访问一次就叫遍历
数组遍历的基本语法:
// 传统遍历 arr[0]; arr[1] // for遍历 1-100 的演变 // 下标 : 0 arr.length-1 // for(var i =0; i < arr.length; i++) { //数组遍历的固定结构 }冒泡排序算法的运作如下: //比较相邻的元素。如果第一个比第二个大,就交换他们两个。 //对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 //针对所有的元素重复以上的步骤,除了最后一个。 //持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var arr = [1,2,3,5,4]; var bianshu = 0; // 遍数 for (var i = 0; i < arr.length-1 ; i++) { var isJiaoHuan = '没有交换'; // var isJiaoHuan = true; bianshu++; // 1 2 3 4 5 // 次数 for (var j = 0 ; j < arr.length-1-i; j++) { if (arr[j] > arr[j+1]) { isJiaoHuan = '交换了'; // isJiaoHuan = false; var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } if ( isJiaoHuan == '没有交换') { // 排好了 break; } } console.log(bianshu); </script> </body> </html>重复代码、冗余代码的缺点:
代码重复,可阅读性差
不易维护,如果代码逻辑改变了,所有地方的代码都要跟着改变,效率太低。
使用场景 : 只要js出现的地方都有函数
特点:
1. 函数声明的时候,函数体并不会执行,函数体只有在调用的时候,才会执行; 2. 可以调用多次;
// 声明函数 function sayHi() { console.log('萨瓦迪卡'); } // 调用函数 sayHi();形参 ( 形式参数 ) : 在函数声明时, 设置的参数。作用是占位置 。只能在函数内部使用.
实参 ( 实际参数 ) : 在函数调用时,传入的参数。 作用 : 函数调用时,会把实参的值赋值给形参, 这样形参就有了值, 在函数体里,可以直接使用形参!
//带参数的函数声明 function 函数名(形参1, 形参2, 形参...){ //函数体 } //带参数的函数调用 函数名(实参1, 实参2, 实参3);如何确定形参:
在声明函数的时候,碰到不确定的值的时候,就可以定义成形参。
注意:
形参在声明时,值不固定,只有在调用的时候,形参的值才确定,形参的值会跟着函数调用时的实参不一样而不一样。
如何确定形参:在声明函数的时候,碰到不确定的值的时候,就可以定义成形参。
当函数执行完的时候,我们期望函数给我一些反馈(比如计算的结果),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值
//声明一个带返回值的函数 function 函数名(形参1, 形参2, 形参...){ //函数体 return 返回值; } //可以通过变量来接收这个返回值 var 变量 = 函数名(实参1, 实参2, 实参3);函数返回值注意事项:
return后面的语句不执行。
函数可以没有返回值,函数如果没有return,那么返回结果是undefined。
函数的参数可以有多个,但是返回值只能有1个。
函数三要素包括:函数名、参数、返回值
注意 : 参数和返回值可以没有,,,但是函数名一定要有;
在函数内部是可以继续调用别的函数的。
function chiFan() { console.log('开始吃饭'); console.log('吃完了'); } function qiaoDaiMa() { console.log('开始敲代码'); chiFan() console.log('代码敲完了'); } qiaoDaiMa()1) 跳到下个断点, 如果后面没有断点了,那么代码直接执行完 ; 2) 单步调试 : 下一步 没有断点的话,,,函数就直接跳过 跳过函数 3) 单步调试 : 进入函数 4) 单步调试 : 跳出函数 5) 单步调试 : 下一步 不管有没有断点,都会一步一会的走,,,纯碎的下一步 6) 让所有的断点失效 7) 自动根据错误断点,性能不好
递归函数:自己直接或者间接调用自己的函数;
注意 : 递归函数一定要留有出口,不然就是死循环了(斐波那契数列)
场景 : 少用,,性能也不太好!
方式1 : 函数声明:
function 函数名(){ //函数体 }方式2 : 函数表达式 ( 匿名函数 )
var 函数名 = function(){ //函数体 }
通常,我们把作为参数传递的函数叫做回调函数
function fn1(fn) { fn(); } fn1(function(){ console.log("哈哈"); });在js高级中,闭包会使用到。
function fn1() { return function(){ console.log("呵呵"); } } fn1()();//调用
作用域:变量起作用的区域
全局作用域 :在script标签内,函数外的区域就是全局作用域,在全局作用内声明的变量叫做全局变量 。全局变量可以在任意地方访问。
函数作用域 :在 函数内的区域 叫做函数作用域,在函数作用域内声明的变量叫做局部变量 ,局部变量只有在当前函数内才能访问到。
全局变量:在函数外,script标签内声明的变量就是全局变量,全局变量在任何地方都能访问的到。
局部变量:在函数中声明的变量,就是局部变量,局部变量只有在当前函数体内能够访问。
隐式全局变量:没有使用var定义的变量也是全局变量,叫做隐式全局变量。(不要使用)
变量的查找规则:
函数内部可以使用函数外部的变量
有局部变量就用局部变量,没有局部变量就用全局变量
js执行代码分为两个过程:
预解析过程(变量与函数提升)
代码一行一行执行
// 预解析过程 // 1. 把var声明的变量提升到当前作用域最前面,不会提升赋值 // 2. 把函数声明 提升到当前作用域的最前面,, // 3. 如果函数同名 ??? 后者会覆盖前者 (帅) // 4. 如果 var声明的 和 函数声明的同名 , 函数优先匿名函数如何使用:
1). 将匿名函数赋值给一个变量,这样就可以通过变量进行调用 2). 自执行(匿名函数自执行)
匿名函数自执行的作用:防止全局变量污染。
var a = 10 var b = 20 b = a (function () { console.log(b); })();现实生活中 : 万物皆对象, 对象是一个具体的事物 , 一个具体的事物就会有 特征 和 行为 ;
JavaScript中: js中的对象就是生活中对象的一个抽象,,,, 没有特征和行为,,取而代之的是有对应的属性和方法 ;
对象 : 是一组无序的键值对的集合
特点 :
1). 声明的变量 = {} []=> 数组 2). 键值对出现 3). 逗号隔开,, 记住 : 以后再 {} 内一行一行的都是用 , 隔开
数组:是有序的元素集合 ,数组用于存放一组有序的数据,比如一个班级所有人的名字,一个班级所有人的成绩。
对象:是一组无序的键值对的集合。 对象用于存放一组无序的数据,比如一个人的特征和行为。
单纯的创建一个对象
字面量 : 直接量,,,通过看数值,,直接看出来类型的 ,或者不需要通过创建, 11, '234', true , [] , {}
var p = {}; var p = { name : 'zs', age:18, sayHi:function(){ console.log(this.name) } }注意 : this使用在对象的属性的函数里,,其他地方使用没有意义
// 设置对象的属性的语法 // 对象.属性 = 值 // 1. 如果对象有这个属性,修改这个属性 // 2. 如果对象没有这个属性,添加这个属
// 语法 对象名.属性 = 值 var obj = new Object(); obj.name = 'zs'; obj.age = 18; obj.gender = '男'; // 添加方法 obj.sayHi = function () { console.log('大家好,我是' + obj.name); }// 获取对象属性的语法: // 对象.属性:对象的属性 // 1. 如果有这个属性,直接返回属性值 // 2. 如果没有这个属性,返回undefined
// 语法 对象名.属性 console.log(obj.name); console.log(obj.age); console.log(obj.gender); //如果是方法,可以调用 obj.sayHi();批量创建对象
在实际开发中,经常需要创建多个相同类型的对象,比如游戏中的怪物,班级的学生等。
优点:可以同时创建多个对象
缺点:创建出来的没有具体的类型,都是object类型的
typeof 只能判断基本数据类型的类型instanceof 判断对象的具体类型constructor.name 也可以获取到对象的具体类型
关于typeof :
typeof用于查看基本的数据类型, number string boolean undefined
typeof如果查看复杂数据类型,返回的都是object类型。
typeof null比较特殊,结果是object
typeof 函数的结果是function:因为函数是一等公民
// 方式1 : typeof console.log(typeof num1); console.log(typeof num2); console.log(typeof num3); console.log(typeof num4); console.log(typeof num5); console.log(typeof num6); console.log(typeof num7); console.log(typeof num8); // typeof 总结 : //1. 简单基本类型 : number string boolean undefined //2. null => object //3. 复杂类型 : object //4. 函数 => fuction 一等公民方式2 : instanceof 判断
结构 : 对象 instanceof 构造函数 var arr = []; var obj = {} var fn = function () {} console.log( arr instanceof Array); // true console.log( obj1 instanceof Object);// true console.log( fn instanceof Function);// true方式3 : constructor.name
// 原型的构造函数 console.log(arr.constructor.name); //Array console.log(obj1.constructor.name); //Object console.log(fn.constructor.name); //Function工厂函数的缺点 就是无法确定对象的具体类型
构造函数 ,是一种特殊的函数。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
//所有创建出来的对象都有: //name //age //hobboy function Teacher(name, age) { //构造函数内部的this指向的是新创建的那个对象 this.name = name; this.age = age; } var tea = new Teacher("zs", 18); console.log(tea);构造函数首字母要大写(推荐做法)。
构造函数要和new一起使用才有意义。
构造函数的作用是用于实例化一个对象,即给对象添加属性和方法。
new在执行时会做四件事情 :
new会做4件事情 //1. new会创建一个新的空对象,类型是Teacher //2. new 会让this指向这个新的对象 //3. 执行构造函数 目的:给这个新对象加属性和方法 //4. new会返回这个新对象 构造函数的作用(实例化对象): 给创建出来的对象增加属性和方法。二者的区别:当属性名是一个字符串存储在变量中的时候,只能使用关联数组的方式。
应用场景 : 遍历对象
通过for..in语法可以遍历一个对象
for (var key in obj) { // 键 console.log(key); // 值 console.log(obj[key]); } 解析 var obj = {}; for (var i = 0; i < 10; i++) { obj[i] = i * 2; } for(var key in obj) { console.log(key + "==" + obj[key]); }结构 :
if (属性名 in 对象) { .. } var obj = { name: 'zs' } if ('name' in obj) { console.log('是'); }
简单数据类型:number、string、boolean、undefined、null
复杂数据类型:Array、function, Object
简单数据类型也叫值类型,复杂数据类型也叫引用数据类型,这主要是根据内存存储方式来区分的。
变量在存储简单类型的时候,存的是值本身(值类型)
变量在存储复杂数据类型的时候,存的是引用,也叫地址(类型)
变量存储数据的时候,存储的直接就是这个值本身。
练习 : var num = 11; var num1 = num; num = 20; console.log(num); console.log(num1);简单类型进行赋值的时候,赋值的是值本身。
复杂类型: 变量不会存这个对象,对象随机存在内存中,会有一个地址,变量存储的仅仅是这个对象的地址。
练习: var obj = { name:"zs", age:18 } var obj1 = obj; obj1.name = "ls"; console.log(obj.name); //ls console.log(obj1.name); //ls 把obj存的地址给了obj1 所以obj和obj1都存放了这个对象的地址,