1.数组基础
数组一组有序的数据的集合,数组内部可以存放多个数据,不限制数据类型,并且数组的长度可以动态的调整
创建数组最简单的方式就是数组字面量的方式
数组字面量:[]
一般把数组字面量赋值给一个变量方便后续操作,存放多个数据,每个数据之间用逗号分隔。
获取数组元素根据下标index(索引值,下标),index从0开始
索引最大项: arr.length - 1;超过数组最大项返回undefined
// 创建一个空数组
var arr = [];
// 创建包含多个数据的数组,数据类型不限制
var arr2 = [1,'23',false,null,undefined,[6,7]];
// 获取arr2中下标为0的项
arr2[0]; // 1
// 更改数据
arr2[0] = 3;
// 获取数组的长度
arr2.length; // 6
// 数组的最后一个项的下标比长度少1
arr2[arr2.length -1 ]; // [6,7];
// 强制改变数组的长度
arr2.length = 9;
// 直接通过index设置比最大项大的赋值,也可以更改数组长度
arr2[10] = 'hhhh';
// 减短数组长度 给arr.length赋值一个比原来长度要小的值,是不可逆的
arr2.length = 5;
数组遍历:从最小的值,遍历到最大的值就可以获取整个数组
for循环
var arr = [56,78,67,89,89,90];
for(var i = 0; i < arr.length - 1; i++){
console.log(arr[i]);
}
// 给每个数据+5
for(var i = 0; i < arr.length; i++){
arr[i] += 5;
}
数组的应用:
- 求一组数中的所有数的和以及平均值
2.函数基础
函数,功能方法 可以将某一段代码一起封装起来,被封装起来的函数具备了某一项特殊的功能,
函数作用:封装一段代码,将来可以重复使用
// 定义函数
function fun(){
console.log(1);
console.log(2);
}
// 调用函数
fun();
fun();
函数声明和调用
函数声明
函数必须先定义后使用,函数声明的时候,函数体不执行,只有当函数调用的时候才执行。
函数名命名规则:
1. 字母数字下划线$,数字不能开头,区分大小写
2. 不能使用关键字和保留字
函数调用:
函数调用,会将封装的代码立即执行
函数内部执行的语句,跟函数的定义无关,跟函数调用有关
函数可以一次定义,多次调用
/*
function 函数名(参数){
函数体
}
*/
function fun() {
console.log(1);
console.log(2);
}
fun();
函数的参数
一个函数可以设置0个或者多个参数,参数之间用逗号分隔。
形参:在函数定义的时候传递的参数
实参:在函数执行的时候传递的参数
// 定义一个求和函数
// 参数:传入两个数字
// 功能: 得到两个数字的和
function sum(a,b){
console.log(a+b);
}
fun(3,5); // 8
函数的返回值
函数能够通过参数接收数据,可以通过返回值返回数据
利用函数内部的一个reutrn 关键字设置函数的返回值
- 函数内部如果遇到return会立即停止执行函数,return后面的代码就不会执行了
- return关键字后面添加一个空格,后面任意定义一个数据字面量或表达式。表达式的值就是return后面的数据
- 函数如果有返回值,执行结果可以当成普通数据参与程序
- 函数如果有返回值i,可以作为一个普通数据赋值给一个变量,甚至赋值给其他函数的实际参数
- 如果函数没有设置return语句,默认返回undefined.如果函数有return语句,但是return后面没有任何值,那么函数的返回值也是undefined;
function sum(a,b){
return a + b;
}
console.log(sum(5,6)); // 11
函数表达式
将函数的定义,匿名函数赋值给一个变量
函数定义赋值给一个变量,相当于将函数整体矮化成了一个表达式。
匿名函数:没有名字的函数
调用函数表达式:变量名加()调用函数
var fum = function (){
console.log(1);
}
函数的数据类型
函数独特数据类型: Function
函数作为另一个函数的参数,在另一个函数中调用
函数作为返回值从函数内部返回
// 函数作为参数
setInterval(function(){
console.log(1);
},2000);
// 函数作为返回值:
function fun(b){
var a = 10;
return function(){
alert(a + b);
}
}
fun(4); // 14
arguments对象
arguments对象中存储了传入的所有实参,是一个伪数组,可以进行遍历
在定义函数,实参的个数可以和形参的个数不相同。
function fun(){
console.log(arguments);
var sum = 0;
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
reutrn sum;
}
fun(1,2,3,4,5,6,7,8);
案例:如果传入两个参数求和,三个参数就比较a,b最大值,再与c相加,4个及以上报错
函数递归
通过函数内部自己调用自己就是递归
函数的递归使用过多会出问题,尽量合理使用递归
/*
传入的参数是1,返回自己
传入参数1以上的数字,返回参数 + 函数调用上一项
*/
function fun(a){
if( a === 1){
return 1;
}else {
return a + fun(a - 1);
}
}
console.log(fun(3)); // 3 + 2 + 1 // 6
案例: 1. 斐波那契数列 11235813
作用域
变量可以起作用范围
如果变量定义在函数内部,变量只能在函数内部被访问,函数外部不能访问 --- 函数作用域
{}包含的是一个块级作用域 -- es5之前没有块级作用域, 只要函数作用域,
现阶段可以认为js没有块级作用域
定义函数内部的变量就是局部变量。变量退出作用域被销毁
函数的参数也是局部变量
全局变量:定义函数外部的变量,任何位置都可以访问到,关闭网页或浏览器被销毁
function fun(){
var a = 1;
console.log(a);
inner();
function inner(){
console.log(a);
}
}
fun(); // 1
console.log(a); // 报错
作用域链:
函数内部指向函数外的链式结构就叫作用域链;
在定义变量的必须写var关键字,否则会定义在全局,造成全局变量污染问题
var a = 1; // 0级
function outer(){
var a = 2; // 1级
function inner(){
var a = 3; // 2级
// 先查找自身作用域有没有a,没有就查找外层是否有啊a,没有就查找全局变量中是否有a,没有就报错 --- 作用域链
console.log(a);
}
}
预解析和声明提升
预解析:
- 把变量的声明提升到作用域的最前面,只会提升声明,不会提升赋值
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用
- 先提升var,再提升function
- 在预解析之后,根据新的代码的顺序,从上往下按照既定规律执行js代码
变量声明提升:在预解析的过程中,所有定义的变量,都会将变量的声明过程提升到当前作用域的最前面。
在使用过程中,尽量避免与函数定义相同的变量名或函数名,避免出现覆盖
定义函数时尽量使用函数关键字定义函数,避免代码提升。
console.log(a);// undefined
var a = 10;
/*
预解析过程:
var a; // 变量声明提前
console.log(a); // 变量只声明未赋值,所以是undefined
a = 10;
*/
fun();
function fun(){
console.log(2);
}
/*
预解析:
function fun(){
console.log(2);
}
fun(); // 2
*/
IIFE自调用函数
即时调用的函数表达式:在函数定义时就立即调用,匿名函数自调用
关键字定义的函数不能立即被执行,函数表达式定义的函数可以
var foo = function (){
console.log(1);
}()
+ function fun(){
console.log(2);
}(); // 不会报错
- function fun(){
console.log(2);
}(); // 不会报错
(function fun(){
console.log(2);
})(); // 不会报错
! function fun(){
console.log(2);
}(); // 不会报错
// 常用的IFE结构
(function fun(a){
console.log(a);
})(2);
3.对象
对象可以自定义名称存储一系列无序的相关数据
万物皆对象,对象是一个具体的事物,一个具体的事物就有行为和特征。
javascript中的对象是无序属性的集合,
属性可以包含基本值,对象或者函数,对象就是一组没有顺序的值,
可以把js中的对象想象成简单的键值对,其中值可以是数据和函数,
特征: 属性 行为:方法
对象字面量
语法: {}
属性:对象的描述性特征 名词 相当于定义在对象内部的变量
方法:对象的行为和功能,一般是动词 定义在对象中函数
/*
var obj = {
k:v,
k:v,
k:v
};
*/
// 对象内部使用this调用
var person = {
name : '张三',
age : 18,
sex : 'male',
sayHi : function (){
console.log(this.name+'说您好');
}
}
// 调用
console.log(person.name);
console.log(person.age);
console.log(person['sex']);
console.log(person[sayHi]());
// 更改
person.age = 19;
// 新增
person.height = 1.98;
// 删除
delete person.sex;
new Object创建对象
var person1 = new Object();
person1.name = '张三';
person1.age = 19;
person1.sex = true;
person1.sayHi = function(){
console.log('您好啊');
};
console.log(person1);
/*
new 会在内存中创建一个新的空对象
new会让this指向这个新对象
执行构造函数,目的:给这个新对象加属性加方法
new会返回这个对象
*/
工厂函数创建对象
function createPerson(name,age,sex){
var person = new Object();
person.name = name;
person.age = age;
person.sex = sex;
person.sayHi = function(){
console.log(this.name + '说您好');
};
return person;
}
var zs = createPerson('张三',18,true);
var ls = createPerson('李四',19,false);
console.log(zs);
console.log(ls);
自定义构造函数
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
this.sayHi = function (){
console.log(this.name + '说你好');
}
}
var p1 = new Person('张三',19,true);
var p2 = new Person('李四',18,false);
console.log(p1);
console.log(p2);
对象遍历 for - in
for(var k in obj){
console.log(k+"项的属性值是"+obj[k]);
}
简单和复杂数据类型
简单类型:基本类型 值类型
在存储时,变量中存储的是值本身,因此叫做值类型
直接把数据复制给变量
复杂类型:引用类型
在存储时,变量中存储的仅仅是地址(引用),因此叫引用类型
如果将原来变量赋值给新变量,如果修改新变量,原来的变量也不会被更改。因为赋值的是地址,不是值。
堆:复杂数据类型的值存储在堆中,在堆中存储的是地址
栈:简单数据类型存储在栈中
数组和函数存储在变量中,也是存储的地址
内置对象
ECMAScript :变量,数据,运算符,条件分支语句,循环语句,函数,数组,对象....
javascript包含三种对象:自定义对象 内置对象 浏览器对象
ECMAScript对象:自定义对象 内置对象
Math对象
// 获取随机数 0-1
// 参数:不需要传递参数
// 返回值: 0 <= < 1
Math.random()
function getRandom(min,max){
return Math.floor(Math.random() * ( max - min ) + min);
}
// 圆周率 3.14159
Math.PI;
//向下取整
Math.floor(123.4); // 123
// 向上取整
Math.ceil(123.2);//124
// 四舍伍入
Math.round(123.4); // 123
Math.round(123.5); // 124
// 绝对值
Math.abs(-5); // 5
// 最大值
Math.max(12,3,24); // 24
var arr = [12,3,24];
Math.max(...arr);
// 最小值
Math.min(12,3,24); // 3
// 次幂
Math.pow(3,4); // 3的4次方 81
// 平分跟
Math.sqrt(9); // 3
数组对象
new Array() 构造函数方法创建对象
// 构造函数创建对象
var arr = new Array(1,2,3,4,5,6,7,8,9);
// instanceof 检查某一实例是否是某个对象类型
console.log(arr instanceof Array); //true
// 1.toString() 转字符串
arr.toString(); // 1,2,3,4
// 2.push 在数组末尾添加一个或多个
// 返回数组新的长度
arr.push(5,6);
// 3.pop 在数组最后一项删除一条数据
// 返回:被删除的数据
arr.pop();
// 4.shift() 在数组第一项数据
// 返回被删除的那一项
arr.shift();// 1
// 5.unshift() 在数组前面添加一项数据
// 返回数组新的长度
arr.unshift(-1,0);
// 6.concat 合并数组
// 返回 新的拼接的数组
// 原数组不改变
var arr1 = arr.concat([1,2,3]); // 1,2,3,4,1,2,3
// 7. slice(s,e) 拆分数组
// 参数可以为负 从 后往前截取
// 一个参数 从开始到结束
// 返回新的值
// 不修改原数组
var arr2 = arr.slice(1,3); // 2 3
// 7.splice 删除 插入 替换
//index:开始的位置
//howmany:个数
//ele1:插入替换的元素
// 删除功能 两个餐宿
// 返回值 删掉的数据组成的数组
arr.splice(1,3); // 从下标为1开始,删除3个元素
// 替换功能
arr.splice(2,5,'哈哈','hello');
// 插入功能
arr.splice(2,0,'hello');
// 8.查找数据在数组中最先出现的下标
// 没找到返回-1
var arr = [8,5,3,4,6,8,9];
arr.indexOf(3); // 从前往后第一次查找出现的下标
arr.lastIndexOf(8); // 从后往前第一次查找出现的下标
// 9.倒序 reverse
arr.reverse();
// 10 sort 字符编码排序 从小到大
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顺序不变
}
});
// 11.转字符串 join()
var str = arr.join('-'); // 1-2-3-4-5-6-7-8-9
// 12.清空数组
arr = [];
arr.length = 0;
arr.splice(0,arr.length);
基本包装类型
在进行基本或者基本类型的数据进行一些特殊操作时,会暂时被包装成一个对象,结束后被销毁
字符串
// 字符串是不可变的,大量字符串拼接的时候会有效率问题
var str = 'abc,def,ghd,efi,gh';
// 1.长度
str.length; // 所有字符的总数 无论是空格还不是空格
// 2. charAt() 返回指定位置的字符
// 参数是 index
str.charAt(2); // c
// 3. indexOf() 返回字符串的值的在字符串中首次出现的位置
// 没有就返回-1
str.indexOf('def'); // 3
// 4. concat() 链接两个或多个字符串
str.concat('klfgfg');
// 5. split 分给字符串成数组
str.split(',');
// 6. toLowerCase 转小写
// toUpperCase 转大写
var str1 = str.toUpperCase();
// 7. slice() 截取字符串 返回新的字符串
var str1 = str.slice(3,7); // 包3不包7
// 8. substr() 从开始位置截取指定长度
// 不写第二个参数 就是开始到结尾
var str2 = str.substr(3,7); // 从3位置 截取 长度为7的字符串
//9. substring 截取两个下标之间的字符
// 顺序可以反, 从小的开始大的结束
// 只有一个参数截取到最后
var str3 = str.substring(4,8);