JavaScript介绍

为什么要学JavaScript?

  • 网页三部分

    • html:控制网页的结构
    • css:控制网页的样式
    • js:控制网页的逻辑
  • 最初的javascript

    • 用于判断客户端的输入(表单校验)
    • 后来一度被用作小广告
  • 现在的JavaScript:现在的JS无所不能

    • 异步与服务器交互(AJAX)
    • 网页和特效
    • 服务端开发(nodejs)
    • 命令行工具开发(nodejs)
    • 桌面程序(Electron)
    • app开发(Cordova)
    • 控制硬件--物联网(Ruff)
    • 游戏开发(cavans, cocos2d-js)

演示:

什么是JavaScript?

JavaScript是一种运行在浏览器端脚本语言 , 现在也可以运行在服务端

不同于HTML和css,JavaScript是一门编程语言,因此要比HTML和css复杂一些,学习的时间也更长。

JavaScript历史

  • 1995年,Netscape(网景)公司的Brendan Eich(布兰登·艾奇)(伊利诺伊大学香槟分校),花了10天时间为Netscape Navigator2.0开发了一个位置为LiveScript的脚本程序,目的是在浏览器中执行预检测程序(表单校验)
  • 后来Netscape在与Sun合作之后将其改名为JavaScript。目的是为了利用 Java 这个因特网时髦词汇。
  • 微软发布了 IE 3.0 并搭载了一个 JavaScript 的克隆版,叫做 JScript(这样命名是为了避免与 Netscape 潜在的许可纠纷)
  • 三足鼎立阶段:
    • CEnvi的scriptEase
    • Netscape的JavaScript
    • IE的JScript
  • 标准化阶段:1997年,ECMA(欧洲计算机制造商协会)邀请了Netscape、Sun、微软、Borland等公司的一些程序员组成了TC39,最终锤炼出来了ECMA-262,该标准定义了一门全新的脚本语言,名为ECMAScript

javascript的组成

ECMAScript - JavaScript的核心

定义了JavaScript的语法规范

JavaScript的核心,描述了语言的基本语法和数据类型,ECMAScript是一套标准,定义了一种语言的标准与具体实现无关

BOM - 浏览器对象模型

一套操作浏览器功能的API

通过BOM可以操作浏览器窗口,比如:弹出框、控制浏览器跳转、获取分辨率等

DOM - 文档对象模型

一套操作页面元素的API

DOM可以把HTML看做是文档树,通过DOM提供的API可以对树上的节点进行操作

JavaScript入门

JavaScript书写位置

JavaScript的代码书写分为两种:

  • 写在script标签中
<script>
  alert('Hello World!');
</script>
  • 引入一个js文件
<script src="main.js"></script>

注意:如果script标签指定了src属性,表示引入一个外部的文件,就不能在写javascript代码了

注释

注释代码不会被执行,仅仅起到一个提示的作用。注释可以对复杂的代码进行解释,方便后期的维护和开发。

  • 单行注释
// 这是单行注释, 单行注释只能写一行代码
//  快捷键: ctrl + /  
  • 多行注释
/*
    这是多行注释,在多行注释中可以
    换行
    快捷键  ctrl + shift + /
/*

【永无bug.js】

在写代码的时候,需要写注释,这是一个良好的习惯

输出语句

  • 警告框alert
//alert会弹出一个警告框
alert("hello world");
  • 确认框confirm
//confirm弹出一个确定框
confirm("你爱我吗?");
  • 输入框prompt
//prompt:弹出一个输入框,可以输入值
prompt("请输入你的银行卡密码");
  • 在网页中输入内容
//可以识别标签
document.write("hello world");
document.write("<h1>hello world</h1>");
  • 在控制台输入
//F12打开控制台,在console中可以看到打印的信息
console.log("hello word");

总结:alert、comfirm、prompt三个用户体验太差,只有在学习的时候会用到。console.log经常用来打印日志,调试的时候非常有用。

变量

变量:可以变化的量。

变量的作用是:存储数据

如何使用变量

  • var声明变量
var age;
  • 变量的赋值
var age;
age = 18;
  • 同时声明并且赋值
var age = 18;
  • 同时声明多个变量并赋值
var age = 10, name = 'zs';
  • 不声明变量,直接赋值(不会报错,但是不推荐)
age = 18;
console.log(age);
  • 不声明变量,也不赋值变量,直接使用(会报错)
console.log(age);

结论:

  • 变量需要声明之后,才能使用,养成一个良好的编程习惯。
  • javascript代码一旦报错了,后面的代码就不再执行了。

变量的命名规则和规范

  • 规则 - 必须遵守的,不遵守会报错

    • 由字母、数字、下划线、$符号组成,不能以数字开头
    • 不能是关键字和保留字,(不用死记,慢慢就见得多了)
    • 区分大小写
  • 规范 - 建议遵守的,不遵守不会报错

    • 变量名必须有意义
    • 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。例如:myName、userPassword
  • 下面哪些变量名不合法

    a	    
    1
    age18
    18age
    2b
    name
    $name
    _sex
    &sex
    theworld
    a b
    

关键字:

保留字:

变量的练习

  1. 交换两个变量的值

数据类型

javascript中数据类型分为简单数据类型和复杂数据类型,今天只学简单数据类型

number、string、boolean、undefined、null

number-数字类型

数字: 11 255 333 1024

浮点数

浮点数就是小数,,比如0.1

  • 浮点数
var num = 0.1;
  • 浮点数精度丢失问题
//在进行浮点数运算的时候,可能会出现精度丢失的问题
0.1 + 0.2 = 0.30000000000000004;
0.2 + 0.2 = 0.4;
//尽量少用浮点数进行运算,不要让浮点数进行比较。

字符串类型

字符串类型,使用双引号 " 或者 ' 包裹起来的字符

//双引号和单引号必须成对出现
var str = 'hello world';
var str = "hello world";

字符串长度

每一个字符串都有一个length属性,可以获取到字符串中字符串的个数

var str = "akdjflksjdflk";
console.log(str.length);

转义字符

思考,如何打印?

//我是一个"老实"的人.
//选择"好看"的外表,还是'有趣'的灵魂

字符串拼接

  • +号具有字符串拼接功能,它能将两个字符串拼接成一个字符串。
  • +号同时具有算术加法的功能,它能将两个数字进行相加
  • 如果+号两边有一个是字符串,那么就是拼串的功能,如果都是数字,那么就是算数的功能。
var a = "hello";
var b = "itcast";
console.log(a + b);//字符串拼接功能

var a = "100";
var b = 100;
console.log(a + b);//字符串拼接功能

var a = 100;
var b = 100;
console.log(a + b);//加法功能

布尔类型

布尔类型:true 和 false

//布尔类型只有两个值
true:表示真
false:表示假

注意:区分大小写,不要写成True或者是False了

undefined和null

  • undefined表示一个没有赋值的变量
  • null表示一个空的对象

字面量与变量

  • 字面量,也叫直接量,值是固定不变的,浏览器能够直接识别的量,比如11, "abc", true, false, undefined, null等都是字面量,可以直接会使用。
  • 变量:浏览器必须要经过声明之后,才认识变量,如果没有声明,直接使用变量是会报错的。

操作符

变量可以存储数据,我们还需要学习操作符来操作这些数据

算术运算符

//快速的说出以下的结果?
console.log(123 + 123);
console.log("123" + 123);
console.log(123 - 123);
console.log(123 - "123");
console.log(12 * "12");
console.log(12 / 12);
console.log(10 % 2);

赋值运算符

赋值运算符有: = , +=, -=, *=, /=, %=

var num = 10;
num += 1;   //num = num + 1;
num -= 1;   //num = num - 1;
num *= 2;   //num = num * 2;
num /= 2;   //num = num / 2;
num % = 2;  //num = num % 2;

一元运算符

一元运算符:只有一个操作数的运算符

二元运算符:有两个操作数的运算符,比如算术运算符、赋值运算符

自增运算符:++

  • 先自增: ++i
  • 后自增:i++
//先自增:
var num = 1;
console.log(++num); //先自增:表示先加1,后返回值

//后自增:
var num = 1;
console.log(num++);// 后自增:表示先返回值,后+1

自减运算符:--

  • 先自减:--i
  • 后自减:i--

练习:

//1. 思考思考
var num = 5;
console.log(num++);
console.log(++num);

//2. 猜猜看
var a = 1; var b = ++a + ++a; console.log(b);    
var a = 1; var b = a++ + ++a; console.log(b);    
var a = 1; var b = a++ + a++; console.log(b);    
var a = 1; var b = ++a + a++; console.log(b);  

逻辑运算符

  • &&:与运算符,表示且,只有当两个操作数都为true的时候,结果才是true
  • ||:或运算符,表示或,只要有其中一个操作数是true,结果就是true
  • !:非运算符,取反
console.log( true && true );
console.log( false && true );
console.log( true && false );
console.log( false && false );

console.log( true || true );
console.log( false || true );
console.log( true || false );
console.log( false || false );

console.log(!true);
console.log(!false);

比较运算符

比较运算符也叫关系运算符, < > >= <= == != === !==, 关系运算符的结果是布尔类型

var a = 5;
var b = 6;
console.log(a > b);//大于
console.log(a < b);//小于
console.log(a >= b);//大于等于
console.log(a <= b);//小于等于

console.log(a == b); //相等,只比较值,不比较类型
console.log(a === b); //全等,比较类型和值
console.log(a != b); // 不等, 只判断值,不判断类型
console.log(a !== b); // 不全等 判断值,且判断类型

运算符优先级

  • ()的优先级最高
  • 一元运算符(++, --, !)
  • 算术运算符(先*/%, 后+-
  • 关系运算符 (先> < >= <=, 后== === != !==)
  • 逻辑运算符(先&&||

不用死记,如果不确定的时候,使用()增加优先级

//猜猜看
var result = ((4 >= 6) || ("人" != "狗")) && !(((12 * 2) == 144) && true);
console.log(result);

//蒙一下
var num = 10;
console.log(5 == num / 2 && (2 + 2 * num).toString() === "22");

类型转换

查看变量的类型

typeof关键字可以查看数据的类型

var num = 11;
console.log(typeof num);
num = "abc";
console.log(typeof num);

**小技巧:在控制台可以根据颜色来判断数据的类型哦(^__^) **

转换成字符串

  • toString()
var num = 5;
console.log(num.toString());// 把数值5变成字符串5
//将来所有的数据都会有toString()方法,除了null和undefined
  • String()
var num = 5;
num = String(num);
console.log(num);
  • 拼串,使用起来最方便
var num = 5;
num = num + "";
console.log(num);

转换成数字类型

  • Number()
console.log(Number('55'));
Number()可以把任意值转换成数值类型,但是如果字符串中有不是数字的字符,返回NaN
  • parseInt()
var num1 = parseInt("12.3abc");  // 返回12,如果第一个字符是数字会解析知道遇到非数字结束
var num2 = parseInt("abc123");   // 返回NaN,如果第一个字符不是数字或者符号就返回NaN
  • parseFloat()
parseFloat()把字符串转换成浮点数
parseFloat()和parseInt()非常相似,不同之处在与
    parseFloat会解析第一个. 遇到第二个.或者非数字结束
    如果解析的内容里只有整数,解析成整数
  • 算术运算
var str = '500';
console.log(+str);		// 取正
console.log(-str);		// 取负
console.log(str - 0);

转换成布尔类型

所有的值都可以转换成布尔类型

其中,""NaNundefinednull0false这几个值会转换成false,其他值都会转换成true

  • Boolean()
console.log(Boolean(1));
console.log(Boolean(0));
  • !!
var a = "abc";
console.log(!!a);

NaN

NaN: not a number, 表示一个非数字

在js中,NaN用来表示一个非数字的特殊值,当发现无法进行运算时,js不会报错,而是会返回一个NaN

NaN的注意事项:

  • NaN的类型是number类型的,表示一个非数字
  • NaN不等于任何值,包括NaN本身
  • 通过isNaN()可以判断是否是一个数字,返回false的时候,表示是一个数字。
var num = 5;
console.log(isNaN(5));

流程控制

程序的三种基本结构

顺序结构

从上到下执行的代码就是顺序结构

程序默认就是由上到下一行一行的顺序执行的

console.log("哈哈1");
console.log("哈哈2");
console.log("哈哈3");

分支结构

分支结构,也叫选择结构,根据不同的情况,执行对应代码

循环结构

循环结构:重复做一件事情

分支结构

if语句

  • 单独的if语句
//语法
if (条件){
  //只有当条件为 true 时执行的代码
}

var age = 8;
if(age < 12) {
  console.log("不准玩王者荣耀");
}
  • if..else语句
if (条件){
  //当条件为 true 时执行的代码
} else {
  //当条件不为 true 时执行的代码
}

var age = 8;
if(age < 12) {
  console.log("不准玩王者荣耀");
}else {
  console.log("可以玩王者荣耀");
}
  • if..else if..else语句
if (条件 1){
  //当条件 1 为 true 时执行的代码
} else if (条件 2) {
  //当条件 2 为 true 时执行的代码
} else {
  //当条件 1 和 条件 2 都不为 true 时执行的代码
}

var age = 8;
if(age < 12) {
  console.log("不准玩王者荣耀");
}else if(age < 18){
  console.log("可以玩王者荣耀2个小时");
}else {
  console.log("可以玩王者荣耀一天");
}

案例:

1. 判断一个数是偶数还是奇数
2. 判断年龄大于16,并且是个男孩,就可以开始撩妹了
3. 如果你有钱 或者 你很帅 ,就可以很快找到女朋友
3. 素质教育,把百分制分数转换成ABCDE   
      A: 90-100
      B: 80-89
    C: 70-79
    D: 60-69
    E: 0-59

三元运算符

用法1:
var 结果 = 判断条件 ? 值1 : 值2 
如果判断条件为true, 结果就是值1, 如果为false, 结果就是 值2

案例:

//思考1:求两个数的最小值
//思考2:判断成年还是未成年
//思考3:求三个数的最小值

switch语句

if..else适用于范围的判断,switch..case适用于具体的值的判断

语法格式:

switch (变量) {
  case 值1:
    语句1;
    break;
  case 值2:
    语句2;
    break;
  case 值3:
    语句3;
    break;
  …
  default:
    默认语句;
    break;
}

注意:

break可以省略,如果省略,代码会继续执行下一个case
switch 语句在比较值时使用的是全等操作符, 因此不会发生类型转换(例如,字符串'10' 不等于数值 10)

案例:

输入一个数字,显示星期几
素质教育(把分数变成ABCDE)千万不要写100个case哟
//测试题:
var num = "10";
switch (num) {
    case 10:
        console.log("10");
    case 20:
        console.log("20");
    case 30:
        console.log("30");
    default:
        console.log("lalala");
}

使用场景

  1. 如果是范围性的判断,使用if..else会更加方便
  2. 如果是对具体值的判断,使用switch..case语句会更加方便,当然用if..else也是可以的。
  3. 如果if..else比较简单,可以使用三元运算符进行替代。
//练习1:土豪的儿子, 输入ABCDE
    //如果考了A:  买玛莎拉蒂
    //如果考了B:  买宝马
    //如果考了C:  买三轮
    //如果考了D:  买摩拜自行车
    //如果考了E:  断绝父子关系
    //如果是其他值,提示代码有bug

//练习2: 买手机,输入自己的工资
   //如果超过30000:  买苹果手机
   //如果10000-30000: 买vivo手机
   //如果5000-10000 : 买魅族手机
   //如果低于5000   : 还买个锤子

//练习3: 输入自己的银行卡金额
    //如果超过1000W  : 高富帅
    //如果不超过      :穷矮丑

循环语句

在javascript中,循环语句有三种,while、do..while、for循环。

while循环

基本语法:

//当循环条件为true时,执行循环体,
//当循环条件为false时,结束循环。
while(循环条件){
  //循环体:需要循环执行的语句
}

代码示例:

//计算1-100之间所有数的和
//1. 初始化变量
var i = 1;
var sum = 0;
while(i <= 100){//判断条件
  sum += i;//循环体
  i++;//自增,修改循环条件(不能省略)
}
console.log(sum);

练习:

//1. 计算所有偶数的和
//2. 循环表白案例
//3. 循环登录案例,只有当用户输入admin的时候才能登录成功,否则一直弹框

do..while循环

do..while循环和while循环非常像,二者经常可以相互替代,但是do..while的特点是不管条件成不成立,都会执行一次。

基础语法:

do{
  //循环体;
}while(循环条件);

代码示例:

//初始化变量
var i = 1;
var sum = 0;
do{
  sum += i;//循环体
  i++;//自增
}while(i <= 100);//循环条件

思考:

// 1. 计算所有偶数的和
// 2. 循环输入账号密码的案例用do..while怎么写?
// 3. 循环表白的案例用do..while怎么写?

思考:

// while循环与do..while循环的区别是啥?

断点调试

断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。

调试步骤:

浏览器中按F12-->sources-->找到需要调试的文件-->在程序的某一行设置断点

调试中的相关操作:

Watch:监视,通过watch可以监视变量的值的变化,非常的常用。
F10:程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。
F8:跳到下一个断点处,如果后面没有断点了,则程序执行结束。

苦口婆心一下:

  1. 代码调试的能力非常重要,只有学会了代码调试,才能学会自己解决bug的能力。初学者不要觉得调试代码麻烦就不去调试,知识点花点功夫肯定学的会,但是代码调试这个东西,自己不去练,永远都学不会。
  2. 今天学的代码调试非常的简单,只要求同学们记住代码调试的这几个按钮的作用即可,后面还会学到很多的代码调试技巧。

for循环(重点)

写while循环的经常会忘记自增,for循环其实是while循环演化过来的,语法更加的简洁明了,使用非常的广泛。

for循环语法:

//1. for循环使用分号分隔
//2. for循环有2个分号,两个分号不能少
for(初始化语句;判断语句;自增语句){
  //循环体
}

执行顺序:1243 ---- 243 -----243(直到循环条件变成false)

  1. 初始化语句
  2. 判断语句
  3. 自增或者自减
  4. 循环体

for循环代码示例:

//计算1-100之间所有数的和
var sum = 0;
for(var i = 1; i <= 100; i++){
  sum += i;
}

思考1:

//1 求1-100之间所有数的和、平均值
//2 求1-100之间所有数的乘积
//3 计算1-100之间能3整除的数的和

思考2:

//1 计算1-100之间不能被7整除的数的和
//2 求1-100之间所有偶数的和
//3 同时求1-100之间所有偶数和奇数的和

思考3(双重for循环):

//1 打印正方形
//2 打印直角三角形
//3 打印9*9乘法表

break和continue

break:立即跳出整个循环,即循环结束,开始执行循环后面的内容(直接跳到大括号)

continue:立即跳出当前循环,继续下一次循环(跳到i++的地方)

思考:

//1. 找到1-100之间第一个能被7整除的数
//2. 打印1-10之间所有的数,除了5这个数

思考1:

//输出结果是什么?
for(var i = 1; i <=10; i++) {
  if(i == 5){
    continue;
  }
  if(i == 7){
    break;
  }
  console.log(i);
}

思考2:

//1. 求1-100之间不能被7整除的整数的和(用continue)
//2. 求200-300之间所有的奇数的和(用continue)
//3. 求200-300之间第一个能被7整数的数(break)

总结

  1. 循环有很多种,但是以后用得最多的是for循环

  2. 当不明确循环次数的时候,可以使用while循环

  3. 当无论如何都要执行一次代码的时候,可以使用do..while循环。

  4. 循环可以相互替代。

数组

所谓数组,就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称之为数组。

数组:多个元素的集合,这个集合有顺序,有长度。用途是存储大量的数据。可以存储任意类型的值,包括复杂数据类型。

思考:

//为什么要有数组?
//1. 我们知道,一个变量能够存储一个值,当我们想要存储多个值的时候,就可以使用数组。比如存储一个班级里面所有学生的姓名。
//2. 使用数组可以对多个相同类型的值统一的管理,存储起来方便,操作的时候也会很方便。

数组初体验

在javascript数组是一个有序的列表,可以在数组中存放任意的数据

创建数组,通过数组的构造函数可以创建一个数组

var arr = new Array();//new表示新的 Array:表示数组  new Array表示创建一个数组。
 注意:var arr=new Array(123);//声明一个长度为123的空数组

通过数组的下标可以操作数组,数组类似于火车车厢

//给数组设置值,数组中可以存放任意的值
//数组名[下标] = "值"    
arr[0] = "张三";//在下标0的地方存放张三
arr[1] = 111; //在下标1的地方存放111
arr[2] = true; //在下标2的地方存放true
//获取数组中的值
//数组名[下标]
console.log(arr[0]);//打印下标0的值

创建数组

通过构造函数创建数组

var arr = new Array();//创建了一个空数组
var arr = new Array("zs","ls","ww");//创建了一个数组,里面存放了3个字符串
var arr = new Array(1,2,3,4);//创建了一个数组,里面存放了4个数字

通过数组字面量创建数组

var arr1 = []; //创建一个空数组
var arr2 = [1, 3, 4]; //创建一个包含3个数值的数组,多个数组项以逗号隔开
var arr3 = ["a", "c"]; // 创建一个包含2个字符串的数组

数组的下标与长度

数组的下标:数组是有序的,数组中的每一个元素都对应了一个下标,下标是从0开始的

var arr = ["zs", "ls", "ww"];

数组的长度:跟字符串一样,数组有一个length属性,指数组中存放的元素的个数。

var arr = ["zs", "ls", "ww"];
arr.length;//这个数组的长度是3
//空数组的长度是0

下标与长度的关系:最大的下标 = length - 1

数组的赋值与取值

数组的取值

//格式:数组名[下标]
//功能:获取数组对应下标的那个值,如果下标不存在,则返回undefined。
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的值

思考:如何给一个数组增加新的元素?

  • 数组名[数组名.length] = 值
  • 数组名.push(值) 注意:工作中常用
//1. 把1-100之间所有的数,放到数组中
//2. 把1-100之间所有的奇数,放到数组中
//3. 把1-100之间能被3整数的数字,存到数组中

数组的遍历

遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。

数组遍历的基本语法:

for(var i =0; i < arr.length; i++) {
    //数组遍历的固定结构
}

思考1:

var arr = [298, 1, 3, 4, 6, 2, 23, 88,77,44];
//1 求一组数中的所有数的和跟平均值
//2 求一组数中的最大值
//3 求一组数中的最小值和最小值所在的位置
//4 求一组数中的最大值和最小值以及所在位置

思考2:

var arr = ["a", "bb","ccc","dddd"];
//1.让一个数组倒叙保存另一个数组中的每一项
//2 将字符串数组用|或其他符号分割
//3 有一个字符串数组,求字符串数组中每项的长度,并把长度的数值存储到新的数组中
//4 将数组中值为0的项去掉,将不为0的值存入一个新的数组

冒泡排序

  1. 初级版本
  2. 中级版本
  3. 高级版本(思路)

声明:我们今天主要是学习数组遍历的语法,对于这种数学烧脑类的题目,想不到是很正常的

//思路:判断,如果一趟下来,一次交换都没有做,说明就已经排好序,就不需要继续比
//var arr = [65, 97, 76, 13, 27, 49, 58];
var arr = [1, 2, 3, 4, 5, 6, 7];

var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {
  tang++;
  var count = 0;//记录交换的次数
  //思路: 两两比较,如果前面的大于后面的,交换位置
  for (var j = 0; j < arr.length - 1 - i; j++) {
    ci++;
    if (arr[j] > arr[j + 1]) {
      count++;
      var temp = arr[j];
      arr[j] = arr[j + 1];
      arr[j + 1] = temp;
    }
  }
  console.log(count);
  if (count == 0) {
    //说明,没有进行交换
    break;
  }
}


console.log(arr);
console.log(tang, ci);

函数

函数基础知识

为什么要有函数

在写代码的时候,有一些常用的代码需要书写多次,如果直接复制粘贴的话,会造成大量的冗余代码。

函数可以封装一段重复的JavaScript代码,它只需要声明一次,就可以被多次调用。

重复代码、冗余代码的缺点:

  1. 代码重复,可阅读性差
  2. 不易维护,如果代码逻辑改变了,所有地方的代码都要跟着改变,效率太低。

函数的声明与调用

声明函数的语法:

function 函数名(){
    //函数体
}

调用函数的语法:

函数名();

特点:

1. 函数声明的时候,函数体并不会执行,函数体只有在调用的时候才会执行,
2. 可以调用多次

代码示例:

//声明函数
function sayHi(){
  console.log("吃了没?");
}
//调用函数
sayHi();

思考:

1. 封装一个打招呼的函数
2. 封装一个函数,计算两个数的和
3. 封装一个函数,计算1-100之间所有数的和

函数的参数

  1. 形参(形式参数):在函数声明时,设置的参数。作用是占位置。
  2. 实参(实际参数):在函数调用时,传入的参数。作用:函数调用时,会把实参的值赋值给形参,这样形参就有了值。

语法:

//带参数的函数声明
function 函数名(形参1, 形参2, 形参...){
  //函数体
}

//带参数的函数调用
函数名(实参1, 实参2, 实参3);

思考:

1. 计算1-n之间所有数的和
2. 计算两个数的和
3. 计算m-n之间所有数的积

注意:

  • 形参在声明时,值不固定,只有在调用的时候,形参的值才确定,形参的值会跟着函数调用时的实参不一样而不一样。
  • 如何确定形参:在声明函数的时候,碰到不确定的值的时候,就可以定义成形参。

函数的返回值

当函数执行完的时候,我们期望函数给我一些反馈(比如计算的结果),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值

返回值语法:

//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参...){
  //函数体
  return 返回值;
}

//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3);

思考:

1. 计算1-n之间所有数的和,并且返回结果
2. 计算两个数的和,并且返回结果
3. 计算m-n之间所有数的积,并且返回结果

注意:

  • 函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。

函数三要素

函数三要素包括:函数名、参数、返回值

function getArea (r) {
    return Math.PI * r * r;
}

思考1:

1. 求任意半径的圆的面积
2. 求任意半径的圆的周长
3. 求任意2个数中的最大值

思考2:

1. 求任意数组中的最大值
2. 求任意数组中的最小值
3. 翻转任意数组,返回一个新的数组
4. 对任意数组从小到大排序

函数高级知识

函数调试

断点调试:

1.	F8:跳到下一个断点,如果后面没有断点了,那么代码直接执行完。
2.	F10:单步调试(跳过函数调用)
3.	F11:单步调试(进入函数调用)
4.	shift+F11:跳出函数调用

函数内部可以调用函数

在函数内部是可以继续调用别的函数的。

function fn1() {
    console.log("fn1开始...");
    fn2();
    console.log("fn1结束...");
}

function fn2 () {
    console.log("执行fn2的代码"); 
    console.log("执行fn2的代码");
    console.log("执行fn2的代码");
}
//在函数1中调用了函数2
fn1();

全局变量与局部变量

全局变量:在最函数外,script标签内声明的变量就是全局变量,全局变量在任何地方都能访问的到。

局部变量:在函数中声明的变量,就是局部变量,局部变量只有在当前函数体内能够访问。

隐式全局变量:没有使用var定义的变量也是全局变量。

var num = 11;//全局变量
function fn() {
  var num1 = 22;//局部变量
  num2 = 33;//隐式全局变量
  console.log(num1);
}
fn();

变量的查找规则:

  • 自己有就用自己的,自己没有就用外面的。
var num = 11;
function fn() {
  var num = 22;
  console.log(num);//22
}
fn();
console.log(num);//11

预解析

js执行代码分为两个过程:

  • 预解析过程(变量与函数提升)
  • 代码一行一行执行

预解析过程:

  1. 函数优先,先提升function,后提升var
  2. 遇到重名的var会被忽略。
  3. 遇到重名的function会被覆盖。

思考:

//1. getCool
//2
console.log(a);
function a() {
  console.log("aaaaa");
}
var a = 1;
console.log(a);

面试题:

//1. 
var num = 10;
fn1();
function fn1() {
  console.log(num);
  var num = 20;
}

//2. 
var a = 18;
fn2();
function fn2() {
    var b = 9;
    console.log(a);
    console.log(b);
}

//3.
fn3();
console.log(c);
console.log(b);
console.log(a);
function fn3() {
  a = b = c = 9;
  console.log(a);
  console.log(b);
  console.log(c);
}

声明函数的两种方式

函数声明(命名函数):

function 函数名(){
  //函数体
}

函数表达式(匿名函数):

var 函数名 = function(){
  //函数体
}

这两种函数声明的区别:

  1. 命名函数可以先调用,在声明,因为预解析
  2. 函数表达式必须先声明,再调用(在DOM中注册事件的时候用的非常的多)

匿名函数

匿名函数:没有名字的函数

匿名函数如何使用:

1. 将匿名函数赋值给一个变量,这样就可以通过变量进行调用
2. 匿名函数自调用

关于自执行函数(匿名函数自调用)的作用:防止全局变量污染。

对象

对象的基本概念

为什么要学习对象?

数组:是有序的元素集合 ,数组用于存放一组数据,比如一个班级所有人的名字,一个班级所有人的成绩。

函数:封装一段重复的代码,只要声明一次,就可以多次调用。

思考1:如果要存储一个人的信息,应该怎么办?
var name = "张三";
var age = 18;
var sex = "男";
var hobby = "上网";
思考2:这么做的缺点是什么?
这些变量都是属于一个人的,应该跟数组一样,使用一个集合把所有的信息都存储起来。

什么是对象

对象:是一组无序的键值对的集合。

//数组多个元素之间使用,隔开
//对象中多个键值对之间也用,隔开,,,键值对的格式: 键:值
var obj = {
  name:"张三",
  age:18,
  sex:"男",
  hobby:"上网"
}
  • 事物的特征在对象中用属性来表示。
  • 事物的行为在对象中用方法来表示。

创建对象

对象字面量

字面量:11 “abc” true [] {}等

var o = {};
var o = {
  name : "zs",
  age : 18,
  sex : true,
  sayHi : function() {
    console.log(this.name);
  }
};

通过Object构造函数创建

var hero = new Object();//创建一个空的对象

操作对象的属性

设置对象的属性

//语法  对象名.属性 = 值;
var obj = new Object();
obj.name = "zs";
obj.age = 18;
obj.gender = "男";

//给对象设置添加一个方法
obj.sayHi = function() {
  console.log("大家好,我是"+obj.name);
}

获取对象的属性

//语法:  对象名.属性
console.log(obj.name);
console.log(obj.age);
console.log(obj.gender);

//如果是方法,可以调用
obj.sayHi();

操作对象的属性

.语法

// 获取对象属性的语法:
    // 对象.属性:对象的属性
    // 1. 如果有这个属性,直接返回属性值
    // 2. 如果没有这个属性,返回undefined
// 设置对象的属性的语法
    // 对象.属性 = 值
    // 1. 如果对象有这个属性,修改这个属性
    // 2. 如果对象没有这个属性,添加这个属性

[]语法

也叫关联数组的方式,其实说白了就是把对象当成数组看待。在中括号中可以是一个变量或者是字符串。

//获取对象属性
    // 对象['下标']   :把对象的属性当成下标
//设置对象的属性
    // 对象['下标'] = "值";

二者的区别:当属性名是一个字符串存储在变量中的时候,只能使用关联数组的方式。

遍历对象

通过for..in语法可以遍历一个对象

for(var key in obj) {
    console.log(key + "==" + obj[key]);
}

批量创建对象

在实际开发中,经常需要创建多个相同类型的对象,比如游戏中的怪物,班级的学生等。

使用工厂函数创建对象

优点:可以同时创建多个对象

缺点:创建出来的没有具体的类型,都是object类型的

function 工厂函数名(属性名-形参,方法-形参){
    var 对象名={
        对象名.属性值;
        对象名.方法;
    };
    return 对象名;
}
工厂函数名();//通过工厂函数创建了对象

构造函数

构造函数 ,是一种特殊的函数。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。

创建同一类型的对象:

function 首字母大写函数名(属性名-形参,方法-形参){
    this.属性值;
    this.方法;
    //自带return返回值
}
var 函数名 = new 首字母大写函数名(属性名-实参,方法-实参参);
  1. 构造函数首字母要大写(推荐做法)。
  2. 构造函数要和new一起使用才有意义。
  3. 构造函数的作用是用于实例化一个对象,即给对象添加属性和方法。

new在执行时会做四件事情

new会做4件事情
1. new会创建一个新的空对象,类型是Teacher
2. new 会让this指向这个新的对象
3. 执行构造函数  目的:给这个新对象加属性和方法
4. new会返回这个新对象

总结:创建对象的几种方式

1. new Object()
2. 对象字面量
3. 工厂函数
4. 自定义构造函数

值类型与引用类型

值类型:简单类型,变量在存储的时候,存储的是值本身。

引用类型:复杂类型,变量在存储的时候,存储的是复杂数据的地址。

值类型与引用类型 内存分布图 (画图说明)

简单类型+复杂类型

值类型与引用类型 赋值 特征(画图说明)

// 值类型
var num1 = 10;
var num2 = num1;
num2 = 99;
console.log(num1);
console.log(num2);

// 引用类型
var obj1 = {
  name:"zs",
  age:18
}
var obj2 = obj1;
obj2.name = "ls";
console.log(obj1.name);
console.log(obj2.name);

值类型与引用类型参数传递(画图说明)

var num = 10;
function fn(a) {
  a = 99;
  console.log(a);
}
fn(num);
console.log(num);

// --------------------------------------

var obj = {
  name:"zs",
  age:18
}
function fn(a) {
  a.name = "ls";
  console.log(a.name);
}
fn(obj);
console.log(obj.name);

值类型与引用类型练习

//面试题1 : 
// a -> x
function fn(a, b) {
  // 相当于
  //  var a = 10;
  //  var b = 20;
  // 函数的参数 其实就是函数内部的局部变量
  a = a + 1;
  b = b + 1;
  console.log(a);
  console.log(b);
}

var x = 10;
var y = 20;
fn(x, y);
console.log(x);
console.log(y);

//面试题2 : 
var p = {
  name:"zs",
  age:18
}
function fn(person) {
  person.name = 'ls';
  console.log(person.name);
}
fn(p);
console.log(p.name);

结论:简单类型存储的是值本身,复杂类型存储的是地址,引入如果把第一个对象赋值给另一个变量,此时两个变量会指向同一个对象。

内置对象

JS内置对象就是指Javascript自带的一些对象,供开发者使用,这些对象提供了一些常用的的功能。

常见的内置对象有Math、String、Array、Date等

JavaScript中的对象分为3种:内置对象、浏览器对象、自定义对象

JavaScript 提供多个内置对象:Math/Array/Number/String/Boolean...

对象只是带有属性方法的特殊数据类型。

学习一个内置对象的使用,只要学会其常用的成员的使用(通过查文档学习)

可以通过MDN/W3C来查询

内置对象的方法很多,我们只需要知道内置对象提供的常用方法,使用的时候查询文档。

MDN

Mozilla 开发者网络(MDN)提供有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及 HTML5 应用的 API。

  • MDN
  • 通过查询MDN学习Math对象的random()方法的使用

如何学习一个方法?

  1. 方法的功能
  2. 参数的意义和类型
  3. 返回值意义和类型
  4. demo进行测试

Math对象

Math对象中封装很多与数学相关的属性和方法。

属性PI

Math.PI

最大值/最小值

Math.max();
Math.min();

取整(★)

Math.ceil();//天花板,向上取整
Math.floor();//地板,向下取整
Math.round();//四舍五入,如果是.5,则取更大的那个数

随机数(★)

Math.random();//返回一个[0,1)之间的数,能取到0,取不到1

取随机整数: parseInt(Math.random()*(n+1));

绝对值

Math.abs();//求绝对值

次幂和平方

Math.pow(num, power);//求num的power次方
Math.sqrt(num);//对num开平方

练习

  随机生成一个rgb颜色?
  function randomRGB(){
    var colorA = parseInt( Math.random() * 256 );
    var colorB = parseInt( Math.random() * 256 );
    var colorC = parseInt( Math.random() * 256 );
    return 'rgb('+ colorA + "," + colorB + ',' + colorC +')';
  }
document.body.style.backgroundColor('rgba('+colorA+','+colorA+','+colorA+')')

Date对象

Date对象用来处理日期和时间

创建一个日期对象

var date = new Date();//使用构造函数创建一个当前时间的对象
var date = new Date("2017-03-22 8:00:00");//创建一个指定时间的日期对象
var date = new Date("2017-03-22 00:52:34");//创建一个指定时间的日期对象
var date = new Date(2017, 2, 22, 0, 52, 34);
var date = new Date(1523199394644);//参数:毫秒值

Date构造函数的参数
1. 毫秒数 1498099000356		new Date(1498099000356)
2. 日期格式字符串  '2015-5-1'	 new Date('2015-5-1')
3. 年、月、日……				 var date = new Date(2017, 2, 22, 0, 52, 34);月份从0开始

日期格式化(了解)

date.toString();//默认的日期格式
date.toLocaleString();//本地风格的日期格式(兼容性)
date.toDateString();//只显示日期
date.toTimeString();//只显示时间
//以下有兼容性问题
date.toLocalDateString();//只显示本地风格的日期,谷歌不兼容
date.toLocalTimeString();//只显示本地风格的时间,谷歌不兼容

获取日期的指定部分

getMilliseconds();//获取毫秒值
getSeconds();//获取秒
getMinutes();//获取分钟
getHours();//获取小时
getDay();//获取星期,0-6    0:星期天
getDate();//获取日,即当月的第几天
getMonth();//返回月份,注意从0开始计算,这个地方坑爹,0-11 ,正常的月份需要加1
getFullYear();//返回4位的年份  如 2019

//思考:
//封装一个函数,返回当前的时间,格式是:yyyy-MM-dd HH:mm:ss
// 年 月 日
var year = getFullYear(),mouth=getMonth()+1,day=getDate();
// 时 分 秒
var hour = getHours(),minutes=getMinutes(),second=getSeconds();
// 获取指定月份有多少天
var days = new Date(year, month, 0).getDate();

// 日期时间加0函数
function addZero(n){
    return n < 10 ? '0' + n : n;
}
function addZero(n){
    return n.toString().padStart(2,'0')
}

// 操作日期追加函数
function add(date,num,type) {
    const dateCopy = new Date(date)
    if(type==='days'){
        dateCopy.setDate(date.getDate() + num)
    } else if (type==='months'){
        dateCopy.setDate(date.getMonth() + num)
    } else if (type==='years'){
        dateCopy.setDate(date.getFullYear() + num)
    }
    return dateCopy
}

时间戳

时间戳是日期的数字形式用于计算时间差

1、统计系统执行时间

//1. 统计代码的执行时间  (可以用于性能优化)
  var start = new Date();
  var sum = 0;    
  for (var i = 1; i < 1e7; i++) {
    sum += i;
  }
  var end = new Date();
  console.log(sum);
  console.log(end - start);

2、秒杀时间

//时间差 单位毫秒
var time = +new Date('结束时间') - +new Date();
//小时
var hour =parseInt(time / 1000 / 3600);
//分
var minutes =parseInt(time / 1000 / 60) % 60;
//秒
var second =parseInt(time / 1000 % 60);
//倒计时
var cutTime = hour+'' + minutes+'' + second;

//老师的写法
// 2. 秒杀倒计时   需要知道倒计时多少时间 = 秒杀时间 - 当前时间
  // 距离下课, 还有多长时间 = 下课时间 - 当前时间
  var future = new Date('2019-7-24 18:30:00');
  var now = new Date();
  var time = parseInt((future - now) / 1000);   // 得到秒数
  // 转换成 时  分  秒
  var hour = parseInt(time / 3600);
  // 分钟, 先求总计多少分钟, 超过60的进位了, 不要了
  var minutes = parseInt(time / 60) % 60;
  // 秒数, 超过60的都进位了
  var seconds = time % 60;
  var str = '距离下课, 还有'+ hour +'时' + minutes + '分'+ seconds +'秒';
  console.log(str);
var date = +new Date();//1970年01月01日00时00分00秒起至现在的总毫秒数
//思考
//1. 如何统计一段代码的执行时间?

//2. 倒计时,计算距离下课还有多长时间

Array对象

数组对象在javascript中非常的常用

数组转换(★)

//语法:array.join(separator)
//作用:将数组的值拼接成字符串

var arr = [1,2,3,4,5];
arr.join();//不传参数,默认按【,】进行拼接
arr.join("-");//按【-】进行拼接

数组的增删操作(★)

//后面的
array.push();//从后面添加一个或者多个元素,返回新数组的length
array.pop();//从数组的后面删除一个元素,返回删除的那个元素,只能按顺序删除一个

//前面的
array.unshift();//从数组的前面的添加一个或者多个元素,返回新数组的长度
array.shift();//从数组的最前面删除一个元素,返回删除的那个元素,,只能按顺序删除一个

练习1

var arr = ["刘备"];
//添加数据后变成:["赵云","马超","刘备","关羽","张飞"]
arr.unshift("赵云","马超");
arr.push("关羽","张飞");
console.log(arr);
//删除数据后变成:["关羽","张飞"]
arr.shift();
arr.shift();
arr.shift();
console.log(arr);
//练习2
var arr = ["赵云","马超","刘备","关羽","张飞"];
//把数组的最后一个元素变成数组的第一个元素
arr.unshift(arr.pop());
//把数组的第一个元素变成数组的最后一个元素
array.push(array.shift(););

数组的翻转与排序

array.reverse();//翻转数组

array.sort();//数组的排序,默认按照字母顺序排序
//默认把数组的第一项转换成字符串,取第一位排序

//sort方法可以传递一个函数作为参数,这个参数用来控制数组如何进行排序
//从小到大
arr.sort(function(a, b){
  //如果返回值>0,则交换位置
  return a - b;
});
//从大到小
arr.sort(function(a, b){
  //如果返回值>0,则交换位置
  return b - a;
});

练习

//思考:
//将[3, 6, 1, 5, 10, 2,11]从小到大排列
array.sort();
//将字符串数组按照字符长度从小到大排列
arr.sort(function(a,b){
    return a.length-b.length;
});
//将学生数组按照年龄从小到大排列
//a,bs是对象
arr.sort(function(a,b){
    return a.age - b.age;
})

数组的合并与截取

//concat:数组合并,不会影响原来的数组,会返回一个新数组。
//可以一次合并一个或多个数组
var newArray = array.concat(array2);

//slice:数组截取,复制数组的一部分到一个新数组,并返回这个数组
//array.slice();默认从头截到尾
var newArray = array.slice(begin, end);//注意:原来的数组不受影响,包含begin,不包含end

//splice:删除数组或者增加数据元素
//start:开始位置  deleteCount:删除的个数  items:替换的内容
array.splice(start, deleteCount, [items]);

//练习:
var arr = ["赵云","马超","刘备","关羽","张飞"];
//截取["刘备","关羽"]
//在马超后面增加 马腾
//删除关羽

splice方法

splice可以在数组的任意位置,添加 删除 替换 (会改变原数组)

arr.splice(start,delnum,itme1,itme2)

//删除
arr.splice(1,1);//删除第二个元素,第一参数下标,第二参数删除个数

//替换
arr.splice(1,1,'李白')//删除第二个元素,替换为别人,可以写多个元素

//添加
arr.splice(2,0,'马云')//在第二个元素,添加元素,可以写多个元素

数组查找元素

常用语判断一个值在数组中是否存在,不存在返回值为-1。

注意:查找所有的位置,使用原始方法遍历

//indexOf方法用来查找数组中某个元素第一次出现的位置,如果找不到,返回-1
arr.indexOf('XXX');
array.indexOf(search, [fromIndex]);

//astIndexOf()从后面开始查找数组中元素出现位置,如果找不到,返回-1
arr.indexOf('XXX');
array.lastIndexOf(search, [fromIndex]);

清空数组

//1. array.splice(0,array.leng);//删除数组中所有的元素
//2.array.length = 0;//直接修改数组的长度
//3.array = [];//将数组赋值为一个空数组,推荐

数组综合练习

var arr = ["c", "a", "z", "a", "x", "a", "a", "z", "c", "x", "a", "x"]
//1. 找到数组中第一个a出现的位置
//2. 找到数组中最后一个a出现的位置
//3. 找到数组中每一个a出现的位置
//4. 数组去重,返回一个新数组
//5. 获取数组中每个元素出现的次数

基本包装类型

简单数据类型是没有方法的。为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String/Number/Boolean。

基本包装类型:把基本类型包装成复杂类型。

var str = “abc”;
//浏览器获取简单类型的属性和方法时,在JS内部,浏览器将简单类型包装成复杂类型
var result = str.indexOf(“a”);
//发生了三件事情
1. 把简单类型转换成复杂类型:var s = new String(str);
2. 调用包装类型的indexOf方法:var result = s.indexOf(“a”);
3. 销毁刚刚创建的复杂类型

Number对象

Number对象是数字的包装类型,数字可以直接使用这些方法

toFixed(2)//保留2位小数
toString();//转换成字符串

Boolean对象

Boolean对象是布尔类型的包装类型。

toString( );//转换成字符串

undefined和null没有包装类型,所以调用toString方法会报错

String对象

字符串可以看成是一个字符数组(伪数组)。因此字符串也有长度,也可以进行遍历。String对象很多方法的名字和和Array的一样。可以少记很多的单词。

查找指定字符串

//indexOf:获取某个字符串第一次出现的位置,如果没有,返回-1
//lastIndexOf:从后面开始查找第一次出现的位置。如果没有,返回-1

去除空白

str.trim();
trim();//去除字符串两边的空格,内部空格不会去除

大小写转换

str.toUpperCase();
str.toLowerCase();
//toUpperCase:全部转换成大写字母
  //toLowerCase:全部转换成小写字母

字符串拼接与截取

//字符串拼接
//可以用concat,用法与数组一样,但是字符串拼串我们一般都用+

//字符串截取的方法有很多,记得越多,越混乱,因此就记好用的就行
//slice :从start开始,end结束,并且取不到end。
//substring :从start开始,end结束,并且取不到end
//substr :从start开始,截取length个字符。

字符串切割

//split:将字符串分割成数组(很常用)
//功能和数组的join正好相反。
var str = "张三,李四,王五";
var arr = str.split(",");
//可以根据空串,把字符串拆分数组
var arr = str.split("");

字符串替换

replace(searchValue, replaceValue)//将str中第一次出现的值替换
str=str.replace('你妹','**');
//参数:searchValue:需要替换的值    replaceValue:用来替换的值

//将所有值替换可以使用正则表达式
str=str.replace(/你妹/g,'**');

练习

//1. 截取字符串"我爱中华人民共和国",中的"中华"
    var str = "我爱中华人民共和国";
       console.log(str.slice(2, 4));
       console.log(str.substring(2, 4));
       console.log(str.substr(2, 2));

//2. "abcoefoxyozzopp"查找字符串中所有o出现的位置
var str = "abcoefoxyozzopp";
  for (var i = 0; i < str.length; i++) {
    if (str[i] === 'o') {
      console.log(i);
    }
  }

//3. 把字符串中所有的o替换成!
var str = "abcoefoxyozzopp";
  str = str.replace(/o/g, '!');
  console.log(str);

//4. 把一个字符串中所有的空格全部去掉
//将所有的 " " =>  ""
  var str = '   aa    bb   ';    // 首尾空格, str.trim()
  str = str.replace(/ /g, '');
  console.log(str);

//5. 统计一个字符串中每个字符出现的次数
// var str = 'my_name_is_jim_green';
  // 需求: 变成驼峰命名  myNameIsJimGreen

  var str = 'my_name_is_jim_green';
  var arr = str.split('_');

  for (var i = 1; i < arr.length; i++) {
    // 让每个单词, 首字母大写
    // console.log(arr[i]);
    arr[i] = arr[i][0].toUpperCase() + arr[i].slice(1);
  }

  // 将数组, 转成字符串
  str = arr.join("");
  console.log(str);