概要
HTML/CSS标记语言--描述类语言
JavaScript脚本语言--编程类语言
JavaScript分为三个部分 ECMAscript(JavaScript语法) DOM(页面文档对象模型) BOM(浏览器对象模型)
ECMAscript规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准
DOM文档对象模型,是W3C推荐的处理可扩展标记语言的标准编程接口,通过DOM提供的接口可以对网页上的各种元素进行操作(大小,位置,颜色等)
BOM浏览器对象模型,他提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率
JS初体验(三种)
行内 内嵌 外部
行内式
<input type="button" name="" id="" value="唐伯虎" onclick="alert('秋香')"/>
内嵌
<script>
alert('琥珀');
</script>
外链
<script src="my.js"></script>
输入输出语句
方法 说明 alert(参数) 浏览器弹出警示框 console.log(参数) 浏览器控制台打印输出信息 prompt(参数) 浏览器弹出输入框,用户可输入 <script> // 这是一个输入框 prompt('请输入您的年龄'); // alert 弹出警示框 输出的 展示给用户的 alert('计算的结果是'); // console 控制台输出 给程序员测试用的 console.log('我是程序员能看到的'); </script>
变量
变量在使用时分为两步: 1.声明变量 2.赋值
//声明变量
var age;
//变量赋值
age = 10;
变量的初始化
var age = 18;
//声明并赋值,我们称为变量的初始化
同时声明多个变量
var age = 22, name = 'Grt', sex = '男';
命名规范
- 由字母,数字,下划线,美元符号组成
- 严格区分大小写
- 不能以数字开头
- 不能是关键字
- 变量名必须有意义
- 遵守驼峰命名法
- 尽量不适用name,有些浏览器有特殊意义
数据类型
为了充分利用空间,所以有不同的数据类型
JavaScript是一种若类型或者说动态语言,不用提前声明变量的类型,生成过程中,会自动确定
var age = 20; //这是数字型
var areyouok = '是的' //这是字符型
JavaScript拥有动态性,意味着相同的变量可用作不同的类型
var x = 6; //x为数字
var x = 'bill'; //x为字符串
简单数据类型(number,string,Boolean,undefined,null)
复杂数据类型(object)
一.数字型
1.进制
八进制前面为0;十六进制前面为0x
2.数字型范围
//数字型的最大值(1.79769e+308)
console.log(Number.MAX_VALUE);
//数字型的最小值(4.94066e-324)
console.log(Number.MIN_VALUE);
3.特殊值
//无穷大
console.log(Number.MAX_VALUE * 2); // Infinity 无穷大
//无穷小
console.log(-Number.MAX_VALUE * 2); // -Infinity 无穷大
//非数字
console.log('你好,中国' - 100); // NaN
4.isNaN()
用来判断非数字,并返回一个值
如果是数字,值为false;
不是数字。值是true;
console.log(isNaN(12)); // false
console.log(isNaN('琥珀')); // true
二.字符串型
var strMsg = "我爱你中国";
var strMsg1 = '中国你好';
//上面两种都正确
//因为HTML标签属性用的是双引号,所以JS推荐使用单引号
1.字符串引号嵌套
var strMsg = "我爱你'前端'";
var strMsg1 = '"前端"你好';
2.字符串转义符
转义符 | 解释说明 |
\n | 换行符 |
\\ | 斜杠\ |
\' | ’单引号 |
\" | ”双引号 |
\t | tab键 |
\b | 空格 |
3.字符串长度--length
//检测获取字符串的长度 length
var str = 'my name is grt';
console.log(str.length); // 14
4.字符串拼接--“+”
数值讲加,字符相连
console.log('沙漠' + '骆驼'); // 字符串的 沙漠骆驼
console.log('pink老师' + 18); // 'pink老师18'
console.log('nihao' + true); // nihaotrue
console.log(12 + 12); // 24
console.log('12' + 12); // '1212'
三.布尔类型
布尔类型有两个值:true和false,其中true表示真(对),而false表示假(错)
布尔类型和数字型相加的时候,true为1,false为0
四.undefined 未定义类型和 null 空类型
如果一个变量声明未赋值,就是 undefined 未定义类型
var str;
console.log(str);
var variable = undefined;
console.log(variable + 'pink'); // undefinedpink
console.log(variable + 1); // NaN undefined 和数字相加 最后的结果是 NaN
// null 空值
var space = null;
console.log(space + 'pink'); // nullpink
console.log(space + 1); // 1
五.判断数据类型--typeof
var num = 10;
console.log(typeof num); // number
var str = 'pink';
console.log(typeof str); // string
var flag = true;
console.log(typeof flag); // boolean
var vari = undefined;
console.log(typeof vari); // undefined
var timer = null;
console.log(typeof timer); // object
// prompt 取过来的值是 字符型的
var age = prompt('请输入您的年龄');
console.log(age);
console.log(typeof age);
六.数据类型的转换
1.转换为字符串
方式 | 说明 | 案例 |
toSrting() | 转成字符串 | var num=1; alert(num.toString()); |
String() 强制转换 | 转成字符串 | var num=1; alert(String(num)); |
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num=1; alert(num+'我是字符串'); |
- toString()和String()使用的方式不一样
- 三种转换,推荐第三中,称为隐式转换
2.转换为数字型
方式 | 说明 | 案例 |
parselnt(string)函数 | 将string类型转成整数数值型 | parselnt(‘78’) |
parseFloat(string)函数 | 将string类型转成浮点数数值型 | parseFloat(‘78.21’) |
Number()强制转换函数 | 将string类型转成数值型 | Number('12') |
js隐式转换(- * /) | 利用算术运算隐式转换为数值型 | '12'-0 |
- 注意 parseInt 和 parseFloat 单词的大小写
- 隐式转换是我们在进行算术运算的时候,JS自动转换了数据类型
3.转换为布尔类型
方式 | 说明 | 案例 |
Boolean()函数 | 其他类型转换为布尔类型 | Boolean(‘true’) |
- 代表空、否定的值会被转换为 false 如 ”、0、null、NaN、undefined
- 其余值都会被转为true
运算符
1.算术运算符
运算符 | 描述 | 实例 |
+ | 加 | 10+20=30 |
- | 减 | 10-20=-10 |
* | 乘 | 10*20=200 |
/ | 除 | 10/20=0.5 |
% | 取余数(取模) | 9%2=1 |
**注意:浮点数存在精度问题**
2.递增递减运算符
2.1前置递增运算符
var age = 10;
++age;
//先加1,后返回值
2.2后置递增运算符
var age = 10;
age++;
//先返回值,后加1
3.比较运算符
运算符名称 | 说明 | 案例 | 结果 |
< | 小于号 | 1<2 | true |
> | 大于号 | 1>2 | false |
>= | 大于等于号 | 2>=2 | true |
<= | 小于等于号 | 3<=2 | false |
== | 判等号(会转型) | 37==37 | true |
!= | 不等于 | 37!=37 | false |
=== !== | 全等(要求值和类型都一致) | 37==='37' | false |
4.逻辑运算符
逻辑运算符 | 说明 | 案例 |
&& | ‘逻辑与’,简称‘与’ and | true&&false |
|| | ‘逻辑或’,简称‘或’ or | true||false |
! | ‘逻辑非’,简称‘非’ not | !true |
短路运算(逻辑中断)
原理:当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续运算右边
1.逻辑与
语法:表达式1&&表达式2
如果第一个表达式值为真,则返回表达式2
如果第一个表达式值为假,则返回表达式1
2.逻辑或
语法:表达式1||表达式2
如果第一个表达式值为真,则返回表达式1
如果第一个表达式值为假,则返回表达式2
5.赋值运算符
赋值运算符 | 说明 | 案例 |
= | 直接赋值 | var userName = 'grt'; |
+=、-= | 加、减一个数后在赋值 | var age =10; age+=5; //15 |
*=、/=、%= | 乘、除、取模后在赋值 | var age =2; age*=5; //10 |
6.运算优先级
优先级 | 运算符 | 顺序 |
1 | 小括号 | () |
2 | 一元运算符 | ++ -- ! |
3 | 算术运算符 | 先* /后+ - |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | == != === !== |
6 | 逻辑运算符 | 先&&后|| |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
一元运算符里面的逻辑非优先级很高,逻辑与比逻辑或优先级高
三种流程控制结构
1.条件结构
if语句
if (条件) {
执行语句;
}
if (条件) {
执行语句;
} else {
执行语句;
}
if (条件) {
执行语句;
} else if {
执行语句;
} else {
执行语句;
}
三元表达式
条件表达式?表达式1:表达式2
//条件表达式为真执行1
//条件表达式为假执行2
switch语句
//switch 语句也是多分支语句 也可以实现多选
//语法结构 switch 转换、开关 case 小例子或者选项的意思
switch (表达式) {
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
...
default:
执行最后的语句;
}
//执行思路 利用我们的表达式的值 和 case 后面的选项值相匹配
//如果匹配上,就执行该case 里面的语句
//如果都没有匹配上,那么执行 default里面的语句
2.循环语句
目的:重复执行某个代码
//for 循环
for (初始化变量;条件表达式;操作表达式) {
循环体;
}
//while 循环
while (条件表达式) {
循环体;
}
// do while循环
do {
循环体;
} while(条件表达式)
continue 关键字 退出当此循环
break 关键字 退出所有循环
数组
数组的创建
①利用new创建数组
var 数组名 = new Array(); var arr = new Array(); //创建要给新的空数组
- 这种方式暂且了解,等学完对象在看
- 注意Array(),A要大写
②利用数组字面量创建数组(常用)
//利用数组字面量方式创建空的数组 [] var 数组名 = []; // 创建了一个空的数组 //利用数组字面量方式创建带初始值的数组 [] var 数组名 = ['小黑', 2, 'pink老师', true];
数组的长度
使用 '数组名.length' 可以访问数组元素的数量 (数组长度)
数组中新增元素
①通过修改length长度新增数组元素
var arr =['red','green','blue','pink'];
arr.length =7;
console.log(arr);
console.log(arr[4]);
console.log(arr[5]);
console.log(arr[5]);
//其中索引号是4,5,6的空间没有给值,就是声明变量未给值,默认值就是undefined
②通过修改数组索引号新增数组元素
- 可以通过修改数组索引的方式追加数组元素
- 不能直接给数组名覆盖,负责会覆盖掉以前的数据
var arr =['red','green','blue','pink']; arr[4] = 'skyblue' console.log(arr);
常见代码
遍历数组
// 遍历数组:就是把数组的元素从头到尾访问一次 var arr = ['red', 'green', 'blue']; for (var i = 0; i < 3; i++) { console.log(arr[i]); } // 1. 因为我们的数组索引号从0开始 ,所以 i 必须从 0开始 i < 3 // 2. 输出的时候 arr[i] i 计数器当索引号来用
筛选数组
// 将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。 // 1、声明一个新的数组用于存放新数据newArr。 // 2、遍历原来的旧数组, 找出大于等于 10 的元素。 // 3、依次追加给新数组 newArr。 // 方法1 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; var j = 0; for (var i = 0; i < arr.length; i++) { if (arr[i] >= 10) { // 新数组索引号应该从0开始 依次递增 newArr[j] = arr[i]; j++; } } console.log(newArr); // 方法2 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; // 刚开始 newArr.length 就是 0 for (var i = 0; i < arr.length; i++) { if (arr[i] >= 10) { // 新数组索引号应该从0开始 依次递增 newArr[newArr.length] = arr[i]; } } console.log(newArr);
数组去重
//将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组。 // 1、需要一个新数组用于存放筛选之后的数据。 // 2、遍历原来的数组, 把不是 0 的数据添加到新数组里面(此时要注意采用数组名 + 索引的格式接收数据)。 // 3、新数组里面的个数, 用 length 不断累加。 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; for (var i = 0; i < arr.length; i++) { if (arr[i] != 0) { newArr[newArr.length] = arr[i]; } } console.log(newArr);
翻转数组
// 将数组 ['red', 'green', 'blue', 'pink', 'purple'] 的内容反过来存放 // 1、声明一个新数组 newArr // 2、把旧数组索引号第4个取过来(arr.length - 1),给新数组索引号第0个元素 (newArr.length) // 3、我们采取 递减的方式 i-- var arr = ['red', 'green', 'blue', 'pink', 'purple', 'hotpink']; var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i] } console.log(newArr);
求数组和以及平均值
// 1. 求数组 [2,6,1,7, 4] 里面所有元素的和以及平均值。 // (1)声明一个求和变量 sum。 // (2)遍历这个数组,把里面每个数组元素加到 sum 里面。 // (3)用求和变量 sum 除以数组的长度就可以得到数组的平均值。 var arr = [2, 6, 1, 7, 4]; var sum = 0; var average = 0; for (var i = 0; i < arr.length; i++) { sum += arr[i]; // 我们加的是数组元素 arr[i] 不是计数器 i } average = sum / arr.length; console.log(sum, average); // 想要输出多个变量,用逗号分隔即可
冒泡排序
// 冒泡排序 // var arr = [5, 4, 3, 2, 1]; var arr = [4, 1, 2, 3, 5]; for (var i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数 for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数 // 内部交换2个变量的值 前一个和后面一个数组元素相比较 if (arr[j] < arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr);
函数
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用
函数的使用分为两步:声明函数和调用函数
//声明函数 function 函数名() { //函数代码 }
- function是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的,所以通常我们将函数命名为动词,比如getSum
//调用函数 函数名(); //通过调用函数名来执行函数代码
- 调用的时候千万不要忘记添加小括号
- 口诀:函数不调用,自己不执行
实参和形参区配问题
参数个数 | 说明 |
实参个数等于形参个数 | 输出正确结果 |
实参个数多于形参个数 | 只取到形参的个数 |
实参个数小于形参个数 | 多的形参定义为undefined,结果为NaN |
arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。在JavaScript中,arguments实际上它是当前函数的一个内置对象,所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参
只有函数才有arguments对象,而且是每个函数都内置好
function fn() { // console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3] // console.log(arguments.length); // console.log(arguments[2]); // 我们可以按照数组的方式遍历arguments for (var i = 0; i < arguments.length; i++) { console.log(arguments[i]); } } fn(1, 2, 3); fn(1, 2, 3, 4, 5); // 伪数组 并不是真正意义上的数组 // 1. 具有数组的 length 属性 // 2. 按照索引的方式进行存储的 // 3. 它没有真正数组的一些方法 pop() push() 等等
参数的返回值
- 如果有return则返回return后面的值
- 如果没有return则返回undefined
// 函数返回值注意事项
// 1. return 终止函数
function getSum(num1, num2) {
return num1 + num2; // return 后面的代码不会被执行
alert('我是不会被执行的哦!')
}
console.log(getSum(1, 2));
// 2. return 只能返回一个值
function fn(num1, num2) {
return num1, num2; // 返回的结果是最后一个值
}
console.log(fn(1, 2)); //返回的为2
// 3. 我们求任意两个数的 加减乘数结果
function getResult(num1, num2) {
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
var re = getResult(1, 2); // 返回的是一个数组
console.log(re);
// 4. 我们的函数如果有return 则返回的是 return 后面的值,如果函数么有 return 则返回undefined
function fun1() {
return 666;
}
console.log(fun1()); // 返回 666
function fun2() {
}
console.log(fun2()); // 函数返回的结果是 undefined
函数的两种声明方式
// 1. 利用函数关键字自定义函数(命名函数) //function 函数名() {} function fn() { console.log('我是函数表达式'); } fn(); // 2. 函数表达式(匿名函数) // var 变量名 = function() {}; var fun = function(aru) { console.log('我是函数表达式'); console.log(aru); } fun('pink老师');
函数表达式
- fun是变量名 不是函数名
- 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 而 函数表达式里面存的是函数
- 函数表达式也可以进行传递参数
例题代码
用户输入年份,输出当前年份2月份的天数
function backDay() { var year = prompt('请您输入年份:'); if (isRunYear(year)) { // 调用函数需要加小括号 alert('当前年份是闰年2月份有29天'); } else { alert('当前年份是平年2月份有28天'); } } backDay();
判断是否为闰年的函数
function isRunYear(year) { // 如果是闰年我们返回 true 否则 返回 false var flag = false; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { flag = true; } return flag; }
利用函数求任意个数的最大值
function getMax() { // arguments = [1,2,3] var max = arguments[0]; for (var i = 1; i < arguments.length; i++) { if (arguments[i] > max) { max = arguments[i]; } } return max; } console.log(getMax(1, 2, 3)); console.log(getMax(1, 2, 3, 4, 5)); console.log(getMax(11, 2, 34, 444, 5, 100));
利用函数翻转任意数组 reverse 翻转
function reverse(arr) { var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } return newArr; } var arr1 = reverse([1, 3, 4, 6, 9]); console.log(arr1); var arr2 = reverse(['red', 'pink', 'blue']); console.log(arr2);
利用函数冒泡排序 sort 排序
function sort(arr) { for (var i = 0; i < arr.length - 1; i++) { for (var j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } var arr1 = sort([1, 4, 2, 9]); console.log(arr1); var arr2 = sort([11, 7, 22, 999]); console.log(arr2);
JS作用域
全局作用域:整个script标签或者是一个单独的JS文件
局部作用域:(函数作用域)在函数内部就是局部作用域,代码名字只在函数内部有效
变量作用域分类
根据作用域不同,变量可以分为两种:局部变量,全局变量
全局变量:在全局作用域下的变量,在全局下都可以使用
注意:如果在函数内部,没有声明直接赋值的变量也属于全局变量
局部变量:在局部作用域下的变量
注意:函数的形参也可以看作是局部变量
块级作用域:{ }
es6的时候新增的,但现阶段无限制
作用域链
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链(就近原则)
var num = 10;
function fn() { // 外部函数
var num = 20;
function fun() { // 内部函数
console.log(num);
}
fun();
}
fn();
//结果为 20
// 案例1 : 结果是几?
function f1() {
var num = 123;
function f2() {
var num = 0;
console.log(num); // 站在目标出发,一层一层的往外查找
}
f2();
}
var num = 456;
f1();
// 案例2 :结果是几?
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 ?
console.log(b); //b的值 ?
}
}
}
fn1();
JS预解析
1. 我们JS引擎运行JS分为两步: 预解析 代码执行
(1). 预解析 JS引擎会把JS里面所有的 var 还有 function 提升到当前作用域的最前面
(2). 代码执行 按照代码书写的顺序从上往下执行
2. 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
(1) 变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
(2) 函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数预解析案例
// 案例1 var num = 10; fun(); function fun() { console.log(num); var num = 20; } // 相当于执行了以下操作 var num; function fun() { var num; console.log(num); num = 20; } num = 10; fun();
// 案例2 var num = 10; function fn() { console.log(num); var num = 20; console.log(num); } fn(); // 相当于以下代码 var num; function fn() { var num; console.log(num); num = 20; console.log(num); } num = 10; fn();
// 案例3 var a = 18; f1(); function f1() { var b = 9; console.log(a); console.log(b); var a = '123'; } // 相当于以下代码 var a; function f1() { var b; var a; b = 9; console.log(a); console.log(b); a = '123'; } a = 18; f1();
// 案例4 f1(); console.log(c); console.log(b); console.log(a); function f1() { var a = b = c = 9; console.log(a); console.log(b); console.log(c); } // 以下代码 function f1() { var a; a = b = c = 9; // 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看 // 集体声明 var a = 9, b = 9, c = 9; console.log(a); console.log(b); console.log(c); } f1(); console.log(c); console.log(b); console.log(a);
JS对象
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串,数值,数组,函数等
对象是由属性和方法组成的
多个变量为什么不用数组?为什么需要对象?
数组的多个数据容易产生歧义,表达不清楚,用对象则能清楚表达含义
var arr= ['琥珀','男',23,180];
琥珀.姓名='琥珀'; 琥珀.性别='男'; 琥珀.年龄=23; 琥珀.身高=180; person.name='琥珀'; person.sex='男'; person.age=23; person.heigh=180;
由此看来对象更清楚表达
创建对象的三种方式
- 利用字面量创建对象
- 利用new Object 创建对象
- 利用构造函数创建对象
1.利用字面量创建对象 {}
// 1.利用对象字面量创建对象 {} //var obj = {}; // 创建了一个空的对象 var obj = { uname: '张三疯', age: 18, sex: '男', sayHi: function() { console.log('hi~'); } }
- 里面的属性或者方法我们采取键值对的形式 键 属性名 : 值 属性值
- 多个属性或者方法中间用逗号隔开的
- 方法冒号后面跟的是一个匿名函数
使用对象
(1). 调用对象的属性 我们采取 对象名.属性名 . 我们理解为 的console.log(obj.uname);
(2). 调用属性还有一种方法 对象名['属性名']console.log(obj['age']);
(3) 调用对象的方法 sayHi 对象名.方法名() 千万别忘记添加小括号obj.sayHi();
2.利用new Object 创建对象
// 利用 new Object 创建对象 var obj = new Object(); // 创建了一个空的对象 obj.uname = '张三疯'; obj.age = 18; obj.sex = '男'; obj.sayHi = function() { console.log('hi~'); } console.log(obj.uname); console.log(obj['sex']); obj.sayHi();
- 我们是利用 等号 = 赋值的方法 添加对象的属性和方法
- 每个属性和方法之间用 分号结束
3.利用构造函数创建对象
- 我们前面两种创建对象的方式一次只能创建一个对象
var ldh = { uname: '刘德华', age: 55, sing: function() { console.log('冰雨'); } } var zxy = { uname: '张学友', age: 58, sing: function() { console.log('李香兰'); } }
- 我们一次创建一个对象,里面很多的属性和方法是大量相同的 我们只能复制
- 因此我们可以利用函数的方法 重复这些相同的代码 我们就把这个函数称为 构造函数
- 又因为这个函数不一样,里面封装的不是普通代码,而是 对象
- 构造函数 就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
语法格式
function 构造函数名() { this.属性 = 值; this.方法 = function() {} }
// new 构造函数名(); function Star(uname, age, sex) { this.name = uname; this.age = age; this.sex = sex; this.sing = function(sang) { console.log(sang); } } var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象 // console.log(typeof ldh); console.log(ldh.name); console.log(ldh['sex']); ldh.sing('冰雨'); var zxy = new Star('张学友', 19, '男'); console.log(zxy.name); console.log(zxy.age); zxy.sing('李香兰')
- 构造函数名字首字母要大写
- 我们构造函数不需要return 就可以返回结果
- 我们调用构造函数 必须使用 new
- 我们只要new Star() 调用函数就创建一个对象 ldh {}
- 我们的属性和方法前面必须添加 this
遍历对象
// 遍历对象
var obj = {
name: 'pink老师',
age: 18,
sex: '男',
fn: function() {}
}
console.log(obj.name);
console.log(obj.age);
console.log(obj.sex);
// for in 遍历我们的对象
// for (变量 in 对象) { }
for (var k in obj) {
console.log(k); // k 变量 输出 得到的是 属性名
console.log(obj[k]); // obj[k] 得到是 属性值
}
// 我们使用 for in 里面的变量 我们喜欢写 k 或者 key
JS内置对象
- JavaScript中的对象分为三种:自定义对象、内置对象、浏览器对象
- 前面两种对象是JS基础内容,属于ECMAScript;第三个浏览器对象属于我们JS独有的,我们JS API讲解
- 内置对象就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能。(属性和方法)
- 内置对象最大的优点就是帮助我们快速开发。
- JavaScript提供多个内置对象:math、Date、Array、String等
学习内置对象的使用,推荐查文档学习,通过 MDN / W3C 来查询
链接:Math - JavaScript | MDN (mozilla.org)
如何学习对象的方法
- 查阅该方法的功能
- 查看里面参数的意义和类型
- 查看返回值的意义和类型
- 通过demo进行测试
MATH对象
// Math数学对象 不是一个构造函数 ,所以我们不需要new 来调用 而是直接使用里面的属性和方法即可 console.log(Math.PI); // 一个属性 圆周率 console.log(Math.max(1, 99, 3)); // 99 console.log(Math.max(-1, -10)); // -1 console.log(Math.max(1, 99, 'pink老师')); // NaN console.log(Math.max()); // -Infinity
Math.PI 圆周率 Math.floor() 向下取整 Math.ceil() 向上取整 Math.round() 四舍五入版 就近取整 注意-3.5 结果 -3 Math.abs() 绝对值 Math.max() / Math.min() 求最大和最小值 // 1.绝对值方法 console.log(Math.abs(1)); // 1 console.log(Math.abs(-1)); // 1 console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型 console.log(Math.abs('pink')); // NaN // 2.三个取整方法 // (1) Math.floor() 地板 向下取整 往最小了取值 console.log(Math.floor(1.1)); // 1 console.log(Math.floor(1.9)); // 1 // (2) Math.ceil() ceil 天花板 向上取整 往最大了取值 console.log(Math.ceil(1.1)); // 2 console.log(Math.ceil(1.9)); // 2 // (3) Math.round() 四舍五入 其他数字都是四舍五入,但是 .5 特殊 它往大了取 console.log(Math.round(1.1)); // 1 console.log(Math.round(1.5)); // 2 console.log(Math.round(1.9)); // 2 console.log(Math.round(-1.1)); // -1 console.log(Math.round(-1.5)); // 这个结果是 -1
Math.random()随机数
// 1.Math对象随机数方法 random() 返回一个随机的小数 0 =< x < 1 // 2. 这个方法里面不跟参数 // 3. 代码验证 console.log(Math.random()); // 4. 我们想要得到两个数之间的随机整数 并且 包含这2个整数 // Math.floor(Math.random() * (max - min + 1)) + min; function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } console.log(getRandom(1, 10)); //应用 // 5. 随机点名 var arr = ['张三', '张三丰', '张三疯子', '李四', '李思思', 'pink老师']; // console.log(arr[0]); console.log(arr[getRandom(0, arr.length - 1)]);
案例--猜数字游戏
// 猜数字游戏 // 1.随机生成一个1~10 的整数 我们需要用到 Math.random() 方法。 // 2.需要一直猜到正确为止,所以需要一直循环。 // 3.while 循环更简单 // 4.核心算法:使用 if else if 多分支语句来判断大于、小于、等于。 function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } var random = getRandom(1, 10); while (true) { // 死循环 var num = prompt('你来猜? 输入1~10之间的一个数字'); if (num > random) { alert('你猜大了'); } else if (num < random) { alert('你猜小了'); } else { alert('你好帅哦,猜对了'); break; // 退出整个循环结束程序 } }
利用对象封装自己的数学对象--里面有 PI 最大值和最小值
var myMath = { PI: 3.141592653, max: function() { var max = arguments[0]; for (var i = 1; i < arguments.length; i++) { if (arguments[i] > max) { max = arguments[i]; } } return max; }, min: function() { var min = arguments[0]; for (var i = 1; i < arguments.length; i++) { if (arguments[i] < min) { min = arguments[i]; } } return min; } } console.log(myMath.PI); console.log(myMath.max(1, 5, 9)); console.log(myMath.min(1, 5, 9));
Date日期对象
- Date对象和Math对象不一样,他是一个构造函数,所以我们需要实例化才能使用
- Date实例用来处理日期和时间
// Date() 日期对象 是一个构造函数 必须使用new 来调用创建我们的日期对象 var arr = new Array(); // 创建一个数组对象 var obj = new Object(); // 创建了一个对象实例 // 1. 使用Date 如果没有参数 返回当前系统的当前时间 var date = new Date(); console.log(date); // 2. 参数常用的写法 数字型 2019, 10, 01 或者是 字符串型 '2019-10-1 8:8:8' var date1 = new Date(2019, 10, 1); console.log(date1); // 返回的是 11月 不是 10月 var date2 = new Date('2019-10-1 8:8:8'); //推荐使用字符串类型 console.log(date2);
日期格式化
方法名 说明 代码 getFullyear() 获取当年 dObj.getFullyear() getmonth() 获取当月(0-11) dObj.getmonth() getDate() 获取当天日期 dObj.getDate() getDay() 获取星期几(周日0到周六6) dObj.getDay() getHours() 获取当前小时 dObj.getHours() getMinutes() 获取当前分钟 dObj.getMinutes() getSeconds() 获取当前秒钟 dObj.getSeconds() // 格式化日期 年月日 var date = new Date(); console.log(date.getFullYear()); // 返回当前日期的年 console.log(date.getMonth() + 1); // 月份 返回的月份小1个月 记得月份+1 呦 console.log(date.getDate()); // 返回的是 几号 console.log(date.getDay()); // 3 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0 // 我们写一个 2021年 5月 1日 星期三 var year = date.getFullYear(); var month = date.getMonth() + 1; var dates = date.getDate(); var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; var day = date.getDay(); console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
// 格式化日期 时分秒 var date = new Date(); console.log(date.getHours()); // 时 console.log(date.getMinutes()); // 分 console.log(date.getSeconds()); // 秒 // 要求封装一个函数返回当前的时分秒 格式 08:08:08 function getTimer() { var time = new Date(); var h = time.getHours(); h = h < 10 ? '0' + h : h; var m = time.getMinutes(); m = m < 10 ? '0' + m : m; var s = time.getSeconds(); s = s < 10 ? '0' + s : s; return h + ':' + m + ':' + s; } console.log(getTimer());
获取日期的总的毫秒形式---距离1970年1月1日
// 获得Date总的毫秒数(时间戳) 不是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数 // 1. 通过 valueOf() getTime() var date = new Date(); console.log(date.valueOf()); // 就是 我们现在时间 距离1970.1.1 总的毫秒数 console.log(date.getTime()); // 2. 简单的写法 (最常用的写法) var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数 console.log(date1); // 3. H5 新增的 获得总的毫秒数 console.log(Date.now());
案例--倒计时效果
- 核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
- 用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
- 把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
转换公式如下: d = parseInt(总秒数/ 60/60 /24); // 计算天数 h = parseInt(总秒数/ 60/60 %24) // 计算小时 m = parseInt(总秒数 /60 %60 ); // 计算分数 s = parseInt(总秒数%60); // 计算当前秒数
function countDown(time) { var nowTime = +new Date(); // 返回的是当前时间总的毫秒数 var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数 var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 var d = parseInt(times / 60 / 60 / 24); // 天 d = d < 10 ? '0' + d : d; var h = parseInt(times / 60 / 60 % 24); //时 h = h < 10 ? '0' + h : h; var m = parseInt(times / 60 % 60); // 分 m = m < 10 ? '0' + m : m; var s = parseInt(times % 60); // 当前的秒 s = s < 10 ? '0' + s : s; return d + '天' + h + '时' + m + '分' + s + '秒'; } console.log(countDown('2019-5-1 18:00:00')); var date = new Date(); console.log(date);
数组对象
数组的创建有两种方式
①利用数组字面量 ②利用new Array()
// 创建数组的两种方式 // 1. 利用数组字面量 var arr = [1, 2, 3]; console.log(arr[0]); // 2. 利用new Array() // var arr1 = new Array(); // 创建了一个空的数组 // var arr1 = new Array(2); // 这个2 表示 数组的长度为 2 里面有2个空的数组元素 var arr1 = new Array(2, 3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3 console.log(arr1);
1.检测是否为数组--instanceof 和 Array.isArray(参数)
// 检测是否为数组 // (1) instanceof 运算符 它可以用来检测是否为数组 var arr = []; var obj = {}; console.log(arr instanceof Array); console.log(obj instanceof Array); // (2) Array.isArray(参数); H5新增的方法 ie9以上版本支持 console.log(Array.isArray(arr)); console.log(Array.isArray(obj));
2.添加删除数组的方法
方法名 说明 返回值 push(参数1.....) 末尾添加一个或多个元素,注意修改原数组 并返回新的长度 pop() 删除数组最后一个元素,数组长度减1。无参数,修改原数组 返回他删除的元素的值 unshift(参数2...) 向数组的开头添加一个或更多元素,注意修改原数组 并返回新的长度 shift() 删除数组的第一个元素,数组长度减1。无参数、修改原数组 并返回第一个元素的值 // 添加删除数组元素方法 // 1. push() 在我们数组的末尾 添加一个或者多个数组元素 push 推 var arr = [1, 2, 3]; // arr.push(4, 'pink'); console.log(arr.push(4, 'pink')); //返回新数组长度 console.log(arr); //返回数组
- push 是可以给数组追加新的元素
- push() 参数直接写 数组元素就可以了
- push完毕之后,返回的结果是 新数组的长度
- 原数组也会发生变化
// 2. unshift 在我们数组的开头 添加一个或者多个数组元素 console.log(arr.unshift('red', 'purple')); //返回新数组长度 console.log(arr);
- unshift是可以给数组前面追加新的元素
- unshift() 参数直接写 数组元素就可以了
- unshift完毕之后,返回的结果是 新数组的长度
- 原数组也会发生变化
// 3. pop() 它可以删除数组的最后一个元素 console.log(arr.pop()); //返回删除的元素 console.log(arr);
- pop是可以删除数组的最后一个元素 记住一次只能删除一个元素
- pop() 没有参数
- pop完毕之后,返回的结果是 删除的那个元素
- 原数组也会发生变化
// 4. shift() 它可以删除数组的第一个元素 console.log(arr.shift()); //返回删除的那个元素 console.log(arr);
- shift是可以删除数组的第一个元素 记住一次只能删除一个元素
- shift() 没有参数
- shift完毕之后,返回的结果是 删除的那个元素
- 原数组也会发生变化
3.翻转数组--reverse()
var arr = ['pink', 'red', 'blue']; arr.reverse(); console.log(arr);
4.冒泡排序--sort()
var arr1 = [3,4,7,1]; arr1.sort(); //只能实现个位数 console.log(arr1) //修改后,可实现 var arr2 = [13, 4, 77, 1, 7]; arr2.sort(function(a, b) { // return a - b; 升序的顺序排列 return b - a; // 降序的顺序排列 }); console.log(arr2);
5.数组索引-- indexOf() 和 lastIndexOf()
方法名 说明 返回值 indexOf() 数组中查找给定元素的第一个索引 如果存在返回索引号 如果不存在,返回-1 lastIndexOf() 在数组中的最后一个的索引 如果存在返回索引号 如果不存在,返回-1 var arr1 = ['red', 'green', 'pink']; console.log(arr1.indexOf('blue'));//-1 var arr2 = ['red', 'green', 'blue', 'pink', 'blue']; console.log(arr2.lastIndexOf('blue')); // 4
案例--数组去重
// 数组去重 ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。 // 1.目标: 把旧数组里面不重复的元素选取出来放到新数组中, 重复的元素只保留一个, 放到新数组中去重。 // 2.核心算法: 我们遍历旧数组, 然后拿着旧数组元素去查询新数组, 如果该元素在新数组里面没有出现过, 我们就添加, 否则不添加。 // 3.我们怎么知道该元素没有存在? 利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有改元素 // 封装一个 去重的函数 unique 独一无二的 function unique(arr) { var newArr = []; for (var i = 0; i < arr.length; i++) { if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]); } } return newArr; } // var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b']) var demo = unique(['blue', 'green', 'blue']) console.log(demo);
6.数组转换为字符串
方法名 说明 返回值 toString() 把数组转换成字符串,逗号分隔每一项 返回一个字符串 join('分隔符') 方法用于把数组中的所有元素转换为一个字符串 返回一个字符串 // 数组转换为字符串 // 1. toString() 将我们的数组转换为字符串 var arr = [1, 2, 3]; console.log(arr.toString()); // 1,2,3 // 2. join(分隔符) var arr1 = ['green', 'blue', 'pink']; console.log(arr1.join()); // green,blue,pink console.log(arr1.join('-')); // green-blue-pink console.log(arr1.join('&')); // green&blue&pink
7.课下了解
方法名 说明 返回值 详细讲解 concat() 连接两个或多个数组,不影响原数组 返回一个新的数组 JavaScript concat() 方法 (w3school.com.cn) slice() 数组截取slice(begin,end) 返回被截取项目的新数组 JavaScript slice() 方法 (w3school.com.cn) splice() 数组删除splice(第几个开始,要删除个数) 返回被删除项目的新数组 注意,这个会影响原数组 JavaScript splice() 方法 (w3school.com.cn) var arr = new Array(6) arr[0] = "George" arr[1] = "John" arr[2] = "Thomas" arr[3] = "James" arr[4] = "Adrew" arr[5] = "Martin" document.write(arr + "<br />")//George,John,Thomas,James,Adrew,Martin arr.splice(2,0,"William") //第二个数组,删除0个,添加William(可添加多个) document.write(arr + "<br />")//George,John,William,Thomas,James,Adrew,Martin //注释:请注意,splice() 方法与 slice() 方法的作用是不同的,splice() 方法会直接对数组进行修改。
字符串对象
1.基本包装类型
为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String、Number、Boolean
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法
var str = 'andy'; console.log(str.length);
按道理基本数据类型没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为JS会把基本数据类型包装为复杂数据类型,其执行过程如下:
// (1) 生成临时变量,把简单类型包装为复杂类型 var temp = new String('andy'); // (2) 把临时变量的值 给 我们声明的字符变量str str = temp; // (3) 销毁这个临时变量 temp = null;
2.字符串不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
var str = 'andy'; console.log(str); str = 'red'; console.log(str); // 因为我们字符串的不可变所以不要大量的拼接字符串 var str = ''; for (var i = 1; i <= 1000000000; i++) { str += i; } console.log(str);//这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
- 当重新给str赋值的时候,常量 ‘andy’ 不会被修改,依然在内存中
- 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
- 由于字符串的不可变,在大量拼接字符串的时候会有效率的问题
3.根据字符串返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串
方法名 说明 indexOf(‘要查找的字符’,开始的位置) 返回指定内容在原字符串中的位置,如果找不到就返回-1,开始的位置是index索引号 lastIndexOf() 从后往前找,只找第一个匹配 // 字符串对象 根据字符返回位置 str.indexOf('要查找的字符', [起始的位置]) var str = '改革春风吹满地,春天来了'; console.log(str.indexOf('春')); console.log(str.indexOf('春', 3)); // 从索引号是 3的位置开始往后查找
案例--查询字符串某个元素出现的次数
- 查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
- 核心算法:先查找第一个o出现的位置
- 然后 只要indexOf 返回的结果不是 -1 就继续往后查找
- 因为indexOf 只能查找到第一个,所以后面的查找,一定是当前索引加1,从而继续查找
var str = "oabcoefoxyozzopp"; var index = str.indexOf('o'); var num = 0; // console.log(index); while (index !== -1) { console.log(index); num++; index = str.indexOf('o', index + 1); } console.log('o出现的次数是: ' + num);
练习作业
课后作业 ['red', 'blue', 'red', 'green', 'pink','red'], 求 red 出现的位置和次数
4.根据位置返回字符(重点)
方法名 说明 使用 charAt(index) 返回指定位置的字符(index字符串的索引号) str.charAt(0) charCodeAt(index) 获取指定位置处的ASCII码(index索引号) str.charCodeAt(0) str[index] 获取指定位置处字符 HTML5,IE8+支持 和charAt()等效 // 1. charAt(index) 根据位置返回字符 var str = 'andy'; console.log(str.charAt(3)); // 遍历所有的字符 for (var i = 0; i < str.length; i++) { console.log(str.charAt(i)); } // 2. charCodeAt(index) 返回相应索引号的字符ASCII值 目的: 判断用户按下了那个键 console.log(str.charCodeAt(0)); // 97 //A 65 a 97 // 3. str[index] H5 新增的 console.log(str[0]); // a
案例--返回字符位置
要求:判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。
- 核心算法:利用 charAt() 遍历这个字符串
- 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
- 遍历对象,得到最大值和该字符
补充知识:
// 有一个对象 来判断是否有该属性 对象['属性名'] var o = { age: 18 } if (o['sex']) { console.log('里面有该属性'); } else { console.log('没有该属性'); }
var str = 'abcoefoxyozzopp'; var o = {}; for (var i = 0; i < str.length; i++) { var chars = str.charAt(i); // chars 是 字符串的每一个字符 if (o[chars]) { // o[chars] 得到的是属性值 o[chars]++; } else { o[chars] = 1; } } console.log(o); // 2. 遍历对象 var max = 0; var ch = ''; for (var k in o) { // k 得到是 属性名 // o[k] 得到的是属性值 if (o[k] > max) { max = o[k]; ch = k; } } console.log(max); console.log('最多的字符是' + ch);
5.字符串操作方法(重点)
方法名
说明 concat(str1,str2,str3...) concat()方法用于连接两个或多个字符串。连接字符串,等效于+,+更常用 substr(start,length) 从start位置开始(索引号),length取的个数,重点记住这个 slice(start,end) 从start位置开始,截取到end位置,end取不到(他们两都是索引号) substring(start,end) 从start位置开始,截取到end位置,end取不到 基本和slice相同 但是不接受负值 // 1. concat('字符串1','字符串2'....) var str = 'andy'; console.log(str.concat('red')); // 2. substr('截取的起始位置', '截取几个字符'); var str1 = '改革春风吹满地'; console.log(str1.substr(2, 2)); // 第一个2 是索引号的2 从第几个开始 第二个2 是取几个字符 // 3.slice('开始位置','结束位置') console.log(str2.slice(3,5));
6.替换字符--replace
// 1. 替换字符 replace('被替换的字符', '替换为的字符') 它只会替换第一个字符 var str = 'andyandy'; console.log(str.replace('a', 'b')); // 有一个字符串 'abcoefoxyozzopp' 要求把里面所有的 o 替换为 * var str1 = 'abcoefoxyozzopp'; while (str1.indexOf('o') !== -1) { str1 = str1.replace('o', '*'); } console.log(str1);
7.字符转换为数组--split
2. 字符转换为数组 split('分隔符') 前面我们学过 join 把数组转换为字符串 var str2 = 'red, pink, blue'; console.log(str2.split(',')); var str3 = 'red&pink&blue'; console.log(str3.split('&'));
8.转换大写/小写--toUpperCase() / toLowerCase()
var str="Hello World!" document.write(str.toUpperCase()) //大写 document.write(str.toLowerCase()) //小写
简单类型和复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型
值类型:简单数据类型 / 基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string、number、Boolean、undefined、null(返回值为一个空对象(特殊))
引用类型:复杂数据类型,咋爱存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过 new 关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等
1.简单数据类型:是存在在栈里面,里面直接开辟一个空间存放的是值
2.复杂数据类型:首先在栈里面存放地址,十六进制表示,然后这个地址指向堆里面的数据
// 简单数据类型传参 function fn(a) { a++; console.log(a); } var x = 10; fn(x); console.log(x);
// 复杂数据类型传参 function Person(name) { this.name = name; } function f1(x) { // x = p console.log(x.name); // 2. 这个输出什么 ? 刘德华 x.name = "张学友"; console.log(x.name); // 3. 这个输出什么 ? 张学友 } var p = new Person("刘德华"); console.log(p.name); // 1. 这个输出什么 ? 刘德华 f1(p); console.log(p.name); // 4. 这个输出什么 ? 张学友