JavaScript
前端三要素
HTML(结构):HTML,超文本标记语言(Hyper Text Markup Language),为前端页面的主体,决定网页的结构和内容。可以理解为一间什么东西都没有的房间
CSS(表现):层叠样式表(Cascading Style Sheets),设定网页的表现样式,可以理解成房间里的地砖,灯,床
JavaScript(行为):是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为,JS为前端页面的脚本。可以理解成房间开灯,关门。
1,什么是JavaScript
1.1概述
JavaScript简称JS,是一种具有函数优先的轻量级、解释型或即时编译型的编程语言。
是一门世界上最流行的脚本语言。
一个合格的后端人员,必须精通JavaScript。
1.2历史
https://blog.csdn.net/kese7952/article/details/79357868
ECMAScript它可以理解为是JavaScript的一个标准
最新版本已经到ES6,但是大部分浏览器还只停留在支持ES5代码上。存在开发环境—-线上环境,版本不一致的问题
2,快速入门
2.1,引入JavaScript
- 内部标签
<script>
alert("hello")
</script>
- 外部引入
<script src="js/js.js"></script>
- 测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--第一种方式,内部引用 -->
<script>
/**
* script标签内写JavaScript代码,script标签必须成对出现。
*/
alert("hello")
</script>
<!--第二种方式,外部引用-->
<script src="js/js.js"></script>
</body>
</html>
2.2,浏览器控制台调试
在页面上可以按F12调出控制台,可以在这里输出当前页面的变量值(或者写脚本),非常方便。
2.3,数据类型
2.3.1快速入门
-
因为JS是弱语言,里面不用声明类型。
-
统一用 var 来声明变量
-
在ES6新增加了let 和const来声明变量。
-
测试代码:
<!--JavaScript严格区分大小写!-->
<script>
// 1. 定义变量 变量类型 变量名 = 变量值;
// 注:在JavaScript中不存在变量类型,一切的变量都叫var,对于var并没有一个固定的变量类型的限制
var score = 71;// 此时score就是一个数字类型的变量
var name='qqqdweob';// 此时name就是一个字符串类型的变量
// alert(score);
// 2. 条件控制
if (score>60 && score<70){
alert("60~70")
}else if(score>70 && score<80){
alert("70~80")
}else{
alert("other")
}
</script>
2.3.2Number
JavaScript不区分浮点数和整数,统一用Number表示,以下都是合法的Number类型:
//--- number
var a = 1;
a = 123//整数
a = 123.1//浮点数
a = -99//负数
a = NaN//not a number,当无法计算结果时用NaN表示
a = 1.2345e3//科学计数法表示1.2345X1000,等同于1234.5
InFinity//InFinity表示无限大,当数值超过了JavaScript的Number能表示的最大值时表示为InFinity
2.3.3字符串
//--- 字符串
var b = "abc";
b = 'cba';
2.3.4布尔值
一个布尔值只有true、false两种值,要么是true,要么是false,可以直接用true、false表示布尔值,也可以通过布尔运算计算出来:
//--- 布尔值
var c = true;
c = false;
true; // 这是一个true值
false; // 这是一个false值
2 > 1; // 这是一个true值
2 >= 3; // 这是一个false值
2.3.5运算符
- 逻辑运算符
//--- 逻辑运算符
&& //两个都为真,结果为真
|| //一个为真,结果为真
! //真即假,假即真
- 比较运算符
//--- 比较运算符
= //赋值运算法
== //等于(类型不一致,值一样,也会判断为true 即判断1=='1')
=== //绝对等于(类型一样,值一样,结果为true)
当我们对Number做比较时,可以通过比较运算符得到一个布尔值:
2 > 5; // false
5 >= 2; // true
7 == 7; // true
实际上,JavaScript允许对任意数据类型做比较:
false == 0; // true
false === 0; // false
须知:
-
由于JavaScript的设计缺陷,不要使用比较,始终坚持使用=比较
-
NaN,not a number,当无法计算结果时用NaN表示,与所有的数值都不相等,包括自己
NaN === NaN; //false
- 只能通过isNaN()来判断这个数是不是NaN
2.3.6浮点数问题
(1/3)===(1-2/3) //结果为false
尽量避免使用浮点数进行运算,存在精度问题
Math.abs(1/3-(1-2/3))<0.00000001 //结果为true
2.3.7null和undefined
- null 空;
它和 0 以及空字符串 “ “ 不同, 0 是一个数值, “ “表示长度为0的字符串,而 null 表示“空”。
-
undefined 未定义
-
大多数情况下,我们都应该用 null 。 undefined 仅仅在判断函数参数是否传递的情况下有用。
2.3.8数组
-
Java的数组必须是相同类型的对象。JS中不需要这样!
-
数组是一组按顺序排列的集合,集合的每个值都称为元素。
-
JS的数组可以包括任意数据类型。例如:
[1, 2, 3.14, 'Hello', null, true];
上述数组包含6个元素。数组用 [] 表示,元素之间用 , 分隔。
- 数组的元素可以通过索引来访问。请注意,索引的起始值为 0 :
var arr = [1, 2, 3.14, 'Hello', null, true]; arr[0]; // 返回索引为0的元素,即1
arr[5]; // 返回索引为5的元素,即true
arr[6]; // 索引超出了范围,返回undefined
-
在浏览器的控制台打印,取数组下标:如果越界了,就会undefined——未定义
2.3.9对象 -
对象是大括号,数组是中括号
-
每一个属性之间使用逗号隔开,最后一个不需要加逗号
-
JavaScript的对象是一组由键-值对组成的无序集合,例如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
-
JS对象的键都是字符串类型,值可以是任意数据类型。上述 person 对象一共定义了6个键值对,其中每个键又称为对象的属性,例如, person 的 name 属性为 ‘Bob’ , zipcode 属性为 null 。
-
取对象的值,我们用 对象变量.属性名 的方式:
person.name; // 'Bob'
person.zipcode; // null
2.3.10变量
-
变量在JS中就是用一个变量名表示
-
变量名是大小写英文、数字、 $ 和 _ 的组合,且不能用数字开头
-
变量名也不能是JS的关键字,如 if 、 while 等
-
申明一个变量用 var 语句,比如:
var a; // 申明了变量a,此时a的值为undefined-未定义
var $b = 1; // 申明了变量$b,同时给$b赋值,此时$b的值为1
var s_007 = '007'; // s_007是一个字符串
var Answer = true; // Answer是一个布尔值true
var t = null; // t的值是null
-
变量名也可以用中文,但是,请不要给自己找麻烦。
-
变量的赋值:
在JS中,使用等号 = 对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用 var 申明一次,例如:
var a = 123; // a的值是整数123
a = 'ABC'; // a变为字符串
- 这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下:
int a = 123; // a是整数类型变量,类型用int申明
a = “ABC”; // 错误:不能把字符串赋给整型变量
-
和静态语言相比,动态语言更灵活,就是这个原因。
-
请不要把赋值语句的等号等同于数学的等号。
2.4.严格检查模式
- JS在设计之初,为了方便初学者学习,并不强制要求使用var声明变量,这个设计错误带来的后果是:如果一个变量没有通过var声明就被使用,那么该变量就自动被声明为全局变量。
i=10;//现在是全局变量
- 在同一个页面的不同的JS文件中,如果都不用 var 声明,而恰好都使用了变量 i ,将造成变量 i 互相影响,产生难以调试的错误结果。
- 使用 var 声明的变量则不是全局变量,它的范围被限制在该变量被声明的函数体内,同名变量在不同的函数体内互不冲突。
- 为了修补JS这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JS代码,强制通过 var 声明变量,未使用 var 声明变量就使用的,将导致运行错误。
- 启用strict模式的方法是在JavaScript代码的第一行写上:
'use strict';
-
这是一个字符串,不支持strict模式的浏览器会把它当作一个字符串语句执行,支持strict模式的浏览器将开启strict模式运行JS。
-
调试自己的浏览器是否能支持strict模式:
'use strict';
//如果浏览器支持strict模式,下面的代码将报ReferenceError错误;
abc='hello world';
console.log(abc);
- 代码部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
前提:Idea,设置支持ES6语法
'use strict';严格检查模式,预防JS随意性导致产生的一些问题
必须写在script标签内的第一行!
局部变量建议都使用let去定义
-->
<script>
'use strict';
let a = 1;
</script>
</body>
</html>
3.数据类型
3.1字符串
- 正常字符串我们使用单引号、双引号包裹
console.log('a');
console.log("a");
- 注意转义字符 \
'i\'m\"ok\"!';
console.log('i\'m\"ok\"!')
i'm"ok!
\ '
\n 表示换行
\t 表示制表符
字符 \ 本身也要转义,所以 \\ 表示的字符就是 \
'\x41'; // 完全等同于 'A';ASCII字符可以以 \x## 形式的十六进制表示
'\u4e2d\u6587'; // 完全等同于 '中文';以用 \u#### 表示一个Unicode字符
- 多行字符串
//tab上面 esc键下面,此处为反引号
var msg=
`hello
world
你好呀
你好ya`
console.log(msg)
hello
world
你好呀
你好ya
- 模板字符串
let name ="zhangsan";
let age =154;
let msg =`你好呀,${name}`//此处为反引号
console.log(msg)
你好呀,zhangsan
- 字符串长度
var student="student"
console.log(student.length)
7
console.log(student[0])
s
- 字符串的可变性——不可变
var student="student"
student[0]=1
1
console.log(student)
student
- 大小写转换
//注意:这里是方法,不是属性了
var student="student"
student.toUpperCase()
STUDENT
student.toLowerCase()
student
- 字符串查找
var student="student"
console.log(student.indexOf('t'))
1
console.log(student.indexOf('u'))
2
- 截取
var student="student"
student.substring(1)//从第一个字符串截取到最后一个字符串
tudent
student.substring(1,3)//下标几到下标几
tu
student.substring(0)
student
3.2数组
JavaScript的 Array 可以包含任意数据类型,并通过索引来访问每个元素。
var arr=[1,2,3,4,5,6]
//通过下标取值和赋值
arr[0]
1
arr[0]=1
1
- 1.长度
var arr=[1,2,3,4,5,6]
arr.length
6
- 注意;假如给iarr.length赋值,数组大小就会发生变化;
如果赋值过小,元素就会丢失
var arr=[1,2,3,4,5,6]
arr.length
6
arr.length=10
10
console.log(arr)
(10)[1,2,3,4,5,6,empty*4]
arr.length=3
3
console.log(arr)
(3)[1,2,3]
- 2.获得下标索引——indexOf()
var arr=[1,2,3,"1","3"]
arr.indexOf(3)
2
arr.indexOf("3")
4
//注意:字符串的"1"和数字的1是不一样的
- 3.数组截取——slice()
截取数组的一部分,返回一个新的数组.类似于string中的substring()
var arr=[1,2,3,4,5,6]
arr.slice(3)
(3) [4,5,6]
-
4.元素操作
-
对尾部元素的操作
push():插入到尾部;
pop():删除尾部的一个元素
var arr=[1,2,3,4,5,6]
arr.push("a","b")
8
arr
(8) [1,2,3,4,5,6,"a","b"]
arr.pop()
"b"
arr
(7) [1,2,3,4,5,6,"a"]
对头部元素进行操作
unshift():插入到头部;
shift():删除头部的一个元素;
var arr=[1,2,3,4,5,6]
arr.unshift("a","b")
8
arr
(8) ["a","b",1,2,3,4,5,6]
arr.shift()
"a"
arr
(7) ["b",1,2,3,4,5,6]
- 5.排序 ——sort()
var arr=["c","b","a"]
arr.sort()
(3) ["a","b","c"]
- 6.元素反转——reverse()
var arr=["a","b","d"]
arr.reverse()
(3) ["d","b","a"]
- 7.concat():把当前的数组和另一个数组连接起来,并返回一个新的数组
var arr = ['A', 'B', 'C'];
arr.concat([1, 2, 3]);
(6) ['A', 'B', 'C', 1, 2, 3]
//注意:concat()并没有修改当前数组,只是返回了一个新的数组
console.log(arr)
(3) ['A', 'B', 'C']
- 8.join()——把当前 Array 的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:
var arr = ['A', 'B', 'C', 1, 2, 3]
arr.join('-');
'A-B-C-1-2-3'
注意:如果 Array 的元素不是字符串,将自动转换为字符串后再连接。
- 9.splice()——splice() 方法是修改 Array 的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素
会改变原来的数组
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook');
// 返回删除的元素
['Yahoo', 'AOL', 'Excite']
arr;
['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2);
['Google', 'Facebook']
arr;
['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook');
// 返回[],因为没有删除任何元素
arr;
['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
- 10.多维数组——如果数组的某个元素又是一个Array,则可以形成多维数组
var arr=[[1,2,3],[200,900,877],'-']
//上述Array包含3个元素,其中头两个元素本身也是Array
//通过索引取到500这个值
arr[0][2]
3
arr[1][1]
900
arr[2]
'-'
3.3对象
- JavaScript的对象是由若干键值对组成的
var 对象名 = {
key: 'value',
key: 'value',
key: 'value'
}
//定义一个对象名为person的对象,有6个属性
var person = {
name: '小明',
birth: 1990,
school: 'No.1 Middle School',
height: 1.70,
weight: 65,
score: null
}
-
在JavaScript中,{………}表示一个对象,键值对描述该对象的具体属性XXX:XXXX,多个属性之间使用逗号隔开,最后一个属性不加逗号!
-
在JavaScript中所有的键都是字符串,值都是任意对象!
-
对象操作
//定义
let person = {
name : "张三",
tags : ['吃饭','睡觉','打豆豆']
}
//由于JavaScript的对象是动态类型,则可以自由的给一个对象添加或删除属性
//1.对象赋值
person.name = "qingjiang"
"qingjiang"
//取值
person.name
"qingjiang"
//取一个不存在的对象属性,不会报错!会显示::undefined
person.haha
undefined
//2.动态的删减属性
//2.1删除属性
delete person.name
true
//2.2添加属性:直接给新的属性添加值即可
person.sex='男'
//取值
person.sex
'男'
//3.判断属性值是否在这个对象中:XXX in XXX
'age' in person
true
//3.1
'toString' in obj; //true,父类中有
//4.判断一个属性是否是这个对象自身拥有的 hasOwnProperty()
person.hasOwnProperty("tostring")
false
person.hasOwnProperty("sex")
true
3.4流程控制
// if 判断
var age = 3
if (age >= 18) {
alert('adult')
}
else if (age >= 6) {
alert('teenager')
}
else {
alert('kid')
}
// while循环
var a = 3
while(a < 10){
a ++;
console.log(a);
}
4,5,6,7,8,9,10
//避免while死循环
while(true){
alert(123)
}
//do..while循环
var n = 0;
do {
n = n + 1;
} while (n < 100)
n
100
// for循环
for(let i = 0; i < 10; i++){
console.log(i);
}
0,1,2,3,4,5,6,7,8,9,10
//forEach循环
var age=[12,22,33,4,100,23,67,88];
//函数
age.forEach(function(value){
console.log(value)
})
12,22,33,4,100,23,67,88
//for in 可以把一个对象的所有属性依次循环出来
var person = {
fame:"John",
lname:"Doe",
age:25
};
var text = "";
var x;
for (x in person) {
text += person[x] + " ";
}
'John Doe 25 '
// for in 遍历下标
var arr=[3,4,5]
for(var x in arr){
console.log(x)
}
0,1,2
//for in 遍历得到值
var arr=[3,4,5]
for(var x in arr){
console.log(arr[x])
}
3,4,5
//通过for of遍历值
var arr=[3,4,5]
for(var x of arr){
console.log(x)
}
3,4,5
3.5Map和Set
-
ES6中增加了Map和Set
-
Map是一组键值对结构,具有极快的查找速度
//假设要根据同学的名字查找对应的成绩,如果用Arry实现,需要两个Arry
var names = ['Michael', 'Bob', 'Tracy'];
var scores = [95, 75, 85];
//需要先在names中找到对应的位置,再从scores取出对应的成绩,Arry越长,耗时越长
如果用Map实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢
var map = new Map([['tom',90],['bob',87],['haha',60]]);
var name = map.get('tom');
console.log(name);
90
- Map的相关操作方法
let map = new Map([['1',"小明"],['2',"小华"],['3',"张三"]]);
map.get('3');
张三
//删除元素
map.delete('1');
map
Map(2) {'2' => '小华', '3' => '张三'}
存在就修改,不存在就添加
map.set('6',"kuangstudy");
Map(3) {'2' => '小华', '3' => '张三', '6' => 'kuangstudy'}
//遍历map
for (let x of map){
console.log(x);
}
(2) ['2', '小华']
(2) ['3', '张三']
(2) ['6', 'kuangstudy']
//是否存在key'Adam'
map.has('Adam')
false
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:
var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam');
88
-
Set:与Map类似,也是一组key的集合,但不存储value,在Set中没有重复的key
-
Set是无序不重复的集合
var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3
- 重复元素在 Set 中自动被过滤:
var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
//注意:数字3和字符串"30"是不同的元素
- Set的相关操作方法
var set = new Set([1, 2, 3]);
//通过 add(key) 方法可以添加元素到 Set 中,可以重复添加,但不会有效果:
set.add(4);
set;
Set {1, 2, 3, 4}
set.add(4);
set;
仍然是 Set {1, 2, 3, 4}
//遍历set
for (var x of set){
console.log(x)
}
1,2,3,4
//通过 delete(key) 方法可以删除元素:
var s = new Set([1, 2, 3]);
s.delete(3);
s;
Set {1, 2}
3.6 Iterable
遍历 Array 可以采用下标循环,遍历Map 和 Set 就无法使用下标。
- 遍历集合
var a = [‘A’,‘B’,‘C’];
var s = new Set([‘A’,‘B’,‘C’]);
var m = new Map([[1,‘x’],[2,‘y’],[3,‘z’]]);
for (var x of a){//遍历Arry
console.log(x)
}
A
B
C
for (var x of s) { // 遍历Set
console.log(x);
}
A
B
C
for (var x of m) { // 遍历Map
console.log(x[0] + ‘=’ + x[1]);
}
1=x
2=y
3=z
- 更好的方式是直接使用 iterable 内置的 forEach 方法,它接收一个函数,每次迭代就自动回调该函数
//以 Array 为例
a.forEach(function (element, index, array) { // element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
console.log(element + ', index = ' + index);
});
-
forEach() 方法是ES5.1标准引入的,需要测试浏览器是否支持。
-
Set 没有索引,因此回调函数的前两个参数都是元素本身:
var s = new Set(['A','B','C']);
s.forEach(function (element,sameElement,set){
console.log(element)
})
A
B
C
- Map 的回调函数参数依次为 value 、 key 和 map 本身:
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
console.log(value);
});
x
y
z
4. 函数
4.1 定义函数
定义方式一
绝对值函数
function abs(x){
if(x >=0){
return x;
}
else{
return -x;
}
}
一旦执行到return代表函数结束,返回结果!
如果没有执行return,函数执行完也会返回结果,结果就是undefined
定义方式二
function abs(x){
if(x >=0){
return x;
}
else{
return -x;
}
}
function(x){………}这是一个匿名函数,将结果赋值给abs,通过abs可以调用函数!
方式一和方式二等价!
调用函数
调用函数时,按顺序传入参数即可:
abs(10)
10
abs(-22)
22
- 由于JavaScript传入任意多个参数也不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
abs(10, 'blablabla');
// 返回10
abs(-9, 'haha', 'hehe', null);
// 返回9
- 传入的参数比定义的少也没有问题:
abs()
//返回NaN
//此时ans(x)函数的参数x将收到undefined,计算结果为NaN
- 假如参数不存在如何规避?——手动抛出异常来判断:
function abs(x) {
if (typeof x !== 'number') {
throw 'Not a number';
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
arguments
-
arguments 是JavaScript中免费赠送的关键字,只在函数内部起作用,并且永远指向当前调用者传入的所有参数
-
利用 arguments ,可以获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值
-
实际上 arguments 最常用于判断传入参数的个数
abs(-10,-12,-13); //只有定义了的参数才会生效
// arguments:代表传递进来的所有参数,是一个数组
function abs(x){
for(let i of arguments){
console.log(i);
}
if(x >= 0){
return x;
}else{
return -x;
}
}
rest参数
- ES6引入了rest参数,主要用以获取除了已定义的参数之外的参数
function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
- rest参数只能写在最后,前面用 … 标识,从运行结果可知,传入的参数先绑定 a 、 b ,多余的参数以数组形式交给变量 rest ,所以,不再需要 arguments 就获取了全部参数。
4.2变量的作用域
变量的作用域
-
在JavaScript中,用var声明的变量实际上是有作用域的
-
在函数体内声明的变量,在函数体外不可以访问
'use strict';
function foo() {
var x = 1;
x = x + 1;
}
x = x + 2;
// ReferenceError: x is not defined
//无法在函数体外引用变量x
- 访问不存在的变量名会报 xxx is defined
function abs(x) {
var a = 1;
}
a = a +2;
//报错:ReferenceError:a is not defined
- 如果两个函数使用了相同的变量名,只要在各自的函数内部,就不冲突;换句话说,不同函数内部的同名变量相互独立,互不影响;
function qj(){
var x = 1;
x =x + 1;
}
function qj2(){
var x = 'A';
x = x + 1;
}
- 内部函数可以访问外部函数的成员,反之则不行!
function qj(){
var x = 1;
//内部函数可以访问外部函数的成员,反之则不行
function qj2(){
var y = x + 1; //2
}
var z = y + 1;//Uncaught ReferenceError: y is not defined
}
- 假设,内部函数变量和外部函数变量重名
function qj() {
var x = 1;
function qj2() {
var x = 'A';
console.log('inner'+x);
}
console.log('outer'+x);
qj2();
}
qj()
//返回的结果:
outer1
innerA
假设在JavaScript中 函数查找变量从自身函数开始,由“内”向“外”查找,假设外部存在这个同名的函数变量,则函数会屏蔽外部函数的变量。
变量提升
- JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
'use strict';
function foo() {
var x = 'Hello, ' + y;
console.log(x);
var y = 'Bob';
}
foo();
//结果:Hello, undefined
//说明 y 的值为 undefined
//这正是因为JavaScript引擎自动提升了变量 y 的声明,但不会提升变量 y 的赋值。
- 对于上述foo()函数,JavaScript引擎看到的代码相当于:
function foo(){
var y;
var x = 'Hello,' + y;
console.log(x);
y = 'Bob';
}
- 由于JavaScript这一特性,我们在函数内部定义变量时,要严格遵守规范:在函数内部首先申明所有变量。最常见的做法是用一个var声明函数内部用到的所有变量:
function foo() {
var x = 1, // x初始化为1
y = x + 1, // y初始化为2
z, i; // z和i为undefined
// 其他语句:
for (i=0; i<100; i++) {
...
}
}
4.3 全局对象 window
- 实际上,JavaScript默认有一个全局对象 window ,全
局作用域的变量实际上被绑定到 window 的一个属性:
'use strict';
var course = 'Learn JavaScript';
alert(course);// 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript
因此,直接访问全局变量course 和访问 window.course 是完全一样的
- 因此,顶层函数的定义也被视为一个全局变量,并绑定到 window 对象:
'use strict'; function foo() {
alert('foo');
}
foo(); // 直接调用foo()
window.foo(); // 通过window.foo()调用
规范
由于我们所有的全局变量都会绑定到我们的window 上,如果不同的js文件,使用了相同的全局变量,冲突~> 如何减少冲突
//唯一全局变量
var xxlApp={};
//定义全局变量
xxlApp.name = "王小姐";
xxlApp.age = function (a,b){
return a + b;
}
let关键字,解决局部作用域冲突问题
function ab(){
for(let i = 0;i<100;i++){
console.log(i);
}
console.log(i);//报错
}
怎么定义常量:只有用全部大写字母命名的变量就是常量,建议不要修改这样的值
var PI = 3.14
console.log(PI);
PI = 123;//可以修改
console.log(PI);
在ES6引入了常量关键字 const
const PI = 3.14; //只读变量
PI = 123;//报错 Attempt to assign to const or readonly variable
console.log(PI);
5、 内部对象
5.1、 Date
data = new Date();
Tue Nov 09 2021 19:05:23 GMT+0800 (中国标准时间)
data.getDate()
9
data.getDay()
2
data.getFullYear()
2021
data.getHours()
19
data.getMinutes()
5
data.getMonth()
10//从0-11
data.getSeconds()
23
time = data.getTime();
1636455923897
new Date(time)
Tue Nov 09 2021 19:05:23 GMT+0800 (中国标准时间)
转换
data = new Date();
Tue Nov 09 2021 19:05:23 GMT+0800 (中国标准时间)
data.toLocaleString()
"2021/11/9 下午7:05:23"
5.2、 Json
早期,所有的数据传输习惯都使用XML文件!
JSON(JavaScript Object Notation,JS对象简谱)是一种轻量级的数据交换格式。
简洁和清晰的层次结构使得JSON成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在JavaScript 中 一切皆为对象,任何js支持的类型都可以用JSON来表示
格式:
对象都用{}
数组都用[]
所有的键值对都用key:value
JSON字符串和JS对象的转换
var user = {
name: '王小姐',
age: 16,
sex: '女'
}
let jsonUser = JSON.stringify(user);
let json = '{"name":"王小姐","age":16,"sex":"女"}';
let parse = JSON.parse(json);
JSON和JS对象的区别
var obj = {name:"王小姐",age:16};
var json = '{"name":"王小姐","age":"16"}';
5.3、 Ajax
原生的js写法 xhr 异步请求
jQuery 封装好的方法 $(“#name”).ajax(“”)
axios 请求
6、 面向对象编程
6.1、 什么是面向对象
javascript、java、c#。。。面向对象,javascript有些区别!
类:模板
对象:具体的实例
在javascript这个需要大家换一下思维方式!
原型:
var user = {
name: "ding",
age: "3",
run: function () {
console.log(this.name + "run.....")
}
};
// 原型对象
var xiaoming = {
name: "xiaoming"
};
var Bird = {
fly: function () {
console.log(this.name+ "fly....")
}
}
// 小明的原型 是user
xiaoming.__proto__ = user;
function Student(name) {
this.name = name;
}
// 给student新增一个方法
Student.prototype.hello = function () {
alert('Hello')
}
class继承
class关键字,是在ES6引入的
class Student{
constructor(name){
this.name = name;
}
hello(){
alert('hello')
}
}
function Student(name) {
this.name = name;
}
// 给student新增一个方法
Student.prototype.hello = function () {
alert('Hello')
}
//ES6之后====
//定义一个学生的类
class Student{
constructor(name){
this.name = name;
}
hello(){
alert('hello')
}
}
class XiaoStudent extends Student{
constructor(name,grade) {
super(name);
this.grade = grade;
}
mygrade() {
alert('我是一名小学生')
}
}
var xiaoming = new Student("xiaoming");
var xiaohong = new Student("xiaohong");
本质:查看对象原型
7、 操作BOM对象(重点)
浏览器介绍
JavaScript和游览器的关系
javascript诞生就是为了能够让他在游览器中运行
BOM:游览器对象模型
-
IE 6~11
-
Chrome
-
Safari
-
FireFox
-
Opera
第三方 -
QQ游览器
-
360
window
window 代表游览器窗口
window.alert(1);
window.innerHeight;
window.innerwidth;
window.outerHeight;
window.outerWidth;
Navigator
Navigator,封装了游览器的信息
navigator.appName;
navigator.appVersioin;
navigator.userAgent;
navigator.platform;
大多数时候,我们不会使用navigator对象,因为会被人为修改~
不建议使用这些属性来判断和编写代码
screen
screen.width
screen.height
//代表屏幕尺寸
location(重要)
location 代表当前页面的URL信息
host: "www.baidu.com"
href: "https://www.baidu.com/"
protocol: "https"
reloadLf reload() //刷新网页
// 设置新的地址
location.assign('新的网站')
document
document 当前的页面,HTML DOM文档树
document.title
document.title='ding'
获取具体的文档树节点
<body>
<dl id="app">
<dt>java</dt>
<dd>python</dd>
<dd>ding</dd>
</dl>
</body>
<script>
var dl = document.getElementById('app');
</script>
获取cookie
document.cookie;
劫持cookie原理
<script src="aa.js"></script>
<!--恶意人员:获取你的cookie上传到他的服务器 -->
服务器端可以设置cookie:httpOnly
history
history.back() //后退
history.forward() //前进
8、 操作DOM对象(重点)
核心
浏览器网页就是一个DOM树形结构!
- 更新:更新Dom节点
- 遍历Dom节点:得到Dom节点
- 删除:删除一个Dom节点
- 添加:添加一个新的节点
要操作一个Dom节点,就必须先获得这个Dom节点
获得Dom节点
//对应 css选择器
var h1 = doucment.getElementByTagName('h1');
var p1 = doucment.getElementById('p1');
var p2 = doucment.getElementByClassName('p2');
var father = doucment.getElementById('father');
//获取父节点下所有的子节点
var childrens = father.children;
//father.firstChild
//father.lastChild
这是原生代码,之后会使用jQuery();
更新节点
<div id='id1'>
<script>
var id1 = document.getElementById('id1');
id1.innerHTML('123')
id1.style.color = 'red';//属性使用''包裹
id1.style.fontSize = '200px';//- 转驼峰命名
id1.style.padding = '2em';
</script>
</div>
删除节点
删除节点的步骤: 先获取父节点,再通过父节点删除自己
<div id="father">
<h1>标题1</h1>
<p id="p1">p1</p>
<p2 class="p2">p2</p2>
</div>
<script>
var self = document.get ElementById('p1');
var father = p1.parentElement;
father.removeChild(self)
//删除时一个动态的过程
father.removeChild(father.children[0])
</script>
注意: 删除多个节点的时候,children时再时刻变化的,删除节点的时候一定要注意!
插入节点
我们获得了某哦个DOM节点,假设DOM节点是空的,我们通过innerHTML就可以增加一个元素了,但是这个DOM节点已经存在元素,我们就不能这样做了,因为会覆盖。
追加
<p id="js">biancheng</p>
<div id="list">
<p id="se">javascript</p>
<p id="ee">java</p>
<p id="py">python</p>
</div>
<script>
var js = document.getElementById('js');
var list = document.getElementById('list');
list.appendChild(js); //追加到后面
</script>
创建一个新的标签,实现插入
var js = document.getElementById('js'); //已经存在的节点
var list = document.getElementById('list');
// 通过js 创建一个新的节点
var newp = document.createElement('p'); //创建一个P标签
newp.id = 'newp';
newp.innerText = 'hello,ding';
list.appendChild(newp)
// 可以创建一个Style标签
var mystyle= document.createElement('style');
mystyle.setAttribute('type','text/css');
// 设置标签内容
mystyle.innerHTML = 'body{background-color: #ffeb3b}';
document.getElementsByTagName('head')[0].appendChild(mystyle)
var ee = document.getElementById('ee');
var py = document.getElementById('py');
var list = document.getElementById('list');
//要包含的节点,insertBefore(new,target)
list.insertBefore(py,ee);
9、 操作表单(验证)
表单时什么 form DOM树
- 文本框 text
- 下拉框 select
- 单选框 radio
- 多选框 checkbox
- 隐藏域 hidden
- 密码框 password
…
表单的目的:提交信息
获得要提交的信息
<form action="post">
<p>
<span>用户名:</span><input type="text" id="username">
</p>
<!--多选框的值,就是定义好的-->
<p>
<span>性别:</span>
<input type="radio" name="sex" value="boy" id="boy"> 男
<input type="radio" name="sex" value="girl" id="girl"> 女
</p>
</form>
<script>
var input_text = document.getElementById('username')
var boy_radio = document.getElementById('boy')
var girl_radio = document.getElementById('girl')
//得到输入框的值
//修改输入框的值
input_text.value = '123'
//对于单选框,多选框等等固定的值,boy_radio.value 只能取到当前的值
boy_radio.checked; //查看返回的结果,是否为true,如果为true 则这个被选中
girl_radio.checked = true;
</script>
提交表单 md5加密密码,表单优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<!--
表单绑定提交事件
onsubmit= 绑定一个提交检测的函数
true,false
讲这个结果返回给表单,使用onsubmit接收!
-->
<form action="https://www.baidu.com" method="post" onsubmit="return submitMsg()">
<p>
<span>用户名</span><input type="text" id="username" name="username">
</p>
<p>
<span>密码</span><input type="password" id="password">
</p>
<p>
<span></span><input type="password" id="pwd" name="password" hidden="hidden">
</p>
<p>
<button type="submit" id="but">提交</button>
</p>
</form>
</div>
<script>
function submitMsg() {
let username = document.getElementById('username').value;
let password = document.getElementById('password').value;
if (username.length < 6 || password.length < 6) {
window.alert("用户名或密码不符合规范");
return false
} else {
password = "别抓了,看不到的,哈哈哈哈哈";
document.getElementById('pwd').value = password;
return true
}
}
</script>
</body>
</html>
10、 jQuery
javascript
jquery库,里面存在大量的javascript函数
获取jquery
https://www.bootcdn.cn/jquery/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
</body>
</html>
使用jquery
<a href="" id="test-jquery">点我</a>
<script>
//选择器就是css选择器
$('#test-jquery').click(function () {
alert('hello,jquery')
})
</script>
选择器
//原生态js,选择器少,麻烦不好记
//标签
document.getElementsByTagName();
//id
document.getElementById();
//类
document.getElementsByClassName();
//jquery css 中的选择器他全部都能用
$('p').click(); //标签选择器
$('#id').click(); //id选择器
$('.class1').click(); //class选择器
公式:
$(selector).action()
事件
鼠标事件,键盘事件,其他事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<style>
#divMove{
width: 500px;
height: 500px;
border: 1px solid red;
}
</style>
</head>
<body>
<!-- 要求:获取鼠标当前的一个坐标-->
mouse: <span id="mouseMove"></span>
<div id="divMove">
在这里移动鼠标试试
</div>
<script>
//当网页元素加载完毕之后,响应事件
$(function () {
$('#divMove').mousemove(function (e) {
$('#mouseMove').text('x:'+e.pageX + 'y:'+e.pageY)
})
})
</script>
</body>
</html>
操作DOM
节点文本操作
$('#test-ul li[name=python]').text(); //获得值
$('#test-ul li[name=python]').text('设置值');//设置值
$('#test-ul').html(); //获得值
$('#test-ul').html('<strong>123</strong>'); //设置值
css的操作
$('#test-ul li[name=python]').css("color","red")
元素的显示和隐藏,本质display:none;
$('#test-ul li[name=python]').show()
$('#test-ul li[name=python]').hide()
娱乐测试
$(window).width()
$(window).height()
$('#test-ul li[name=python]').toggle();