JavaScript
什么是JavaScript
-
JavaScript是一门世界上最流行的脚本语言
-
ECMAScript它可以理解为是JavaScript的一个标准,最新版本已经到es6版本,但是大部分浏览器还是只停留在支持es5代码上,开发环境与线上环境,版本不一致。
快速入门
引入JavaScript
-
内部标签
<script> //.... </script>
-
外部引入
abs.js
//....
test.html
<srcipt src="abs.js"></srcipt>
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--script标签内,写JavaScript代码-->
<!-- <script>-->
<!-- alert("hello,world");-->
<!-- </script>-->
<!-- 外部引入-->
<!-- 注意:script标签必须成对出现-->
<script src="js/qj.js"></script>
<!-- 不用显示定义type,也默认就是-->
<script type="text/javascript"></script>
</head>
<body>
<!--这里也可以存放JavaScript的脚本-->
</body>
</html>
基本语法入门
<!-- JavaScript严格区分大小写!-->
<script>
// 1.定义变量 变量类型 变量名 = 变量值
var score = 3;
// 条件控制
if(score>60&&score<70){
alert("60~70");
}else if (score>70&&score<80){
alert("70~80");
}else {
alert("other");
}
/*console.log(score) 在浏览器的控制台打印变量!
*
* */
</script>
数据类型
数值,文本,图新,音频,视频…
变量
var a =1;
number
js不区分小数和整数,Number
123//整数123
123.1//浮点数123.1
1.23e3//科学计数法
-99//负数
NaN//not a number
Infinity//表示无限大
字符串
“abc” ‘abc’
布尔值
true,fasle
逻辑运算
&& 两个都为真,结果为真
|| 两个都为假,结果为假
! 真为假,假为真
比较运算符!!!重要
= 赋值
== 等于(类型不一样,值一样,也会判断为true。例console.log(“123”==123)结果为true
=== 绝对等于(类型一样值一样,结果才为true)
这是一个js的缺陷,坚持不要用 == 号比较
须知:
- NaN===NaN,这个与所有的数值都不相等,包括自己
- 只能通过isNaN(NaN)来判断这个数是否是NaN
浮点数问题:
console.log((1/3)===(1-2/3))
尽量避免使用浮点数进行运算,存在精度问题。
(Math.abs(1/3-(1-2/3))<0.00000001
一个数减另一个数小于0.000000000001基本上这两个数就是相等的
NULL 和 undefined
- null 空
- undefined 未定义
数组
Java中的数组必须是一系列相同类型的对象,但js中不需要这样定义;
//保证代码的可读性,尽量使用[]
var arr = [1,2,3,5,4,"hello",null]
new Array(1,2,4,5,6,"hello",true)
取数组下标:如果越界了,就会
undefined
对象
-
对象是用大括号,数组是用中括号
-
每个属性之间使用逗号隔开,最后一个不需要添加
//java中:Person person = new Person();
//js中:
var Person = {
name:"fengzi",
age: 3,
tags:['js','java','web']
}
取对象的值
Person.name
> "fegnzi"
Person.sge
> 3
严格检查模式
- ‘use strict’
//严格检查模式,必须写在JavaScript的第一行
'use strict';//预防JavaScript的随意性导致产生的一些问题
//局部变量建议都使用 let 去定义
let i=1;
数据类型
字符串
-
正常的字符串我们使用,单引号,或者双引号包裹
-
注意转义字符 \
\' \n \t \u4e2d \u#### Unicode字符 \x41 Ascll字符
-
多行字符串编写
//tab 键上面的符号 var msg = `hello world 你好 `
-
模板字符串
//tab 键上面的符号 let name = "fengzi"; let age = 3; let msg=`你好啊,${name}`
-
字符串长度
str.lenth
-
字符串的可变性,不可变
var student = "student"; undefined console.log(student.length) VM188:1 7 undefined student[0]=1 1 console.log(student) VM264:1 student//说明赋值失败,字符串不可变
-
大小写转换
//注意,这里是方法,不是属性 student.toUpperCase() student.toLowerCase()
-
获取指定字符的下标
student.indexOf('t')
-
substring
student.substring(1)//从第一个字符串截取到最后一个字符串 tudent student.substring(1,3)//[1.3) tu
数组
-
Array可以包含任意的数据类型
var arr=[1,2,"hello",true,'h'];//通过下标取值和赋值 arr[0] arr[0] = 1
-
长度是可变的
arr.length
注意:假如给 arr.length 赋值,数组大小就会发生变化,如果赋值过小,元素就会丢失
-
indexOf,通过元素获得下标索引
arr.indexOf(2) 1
字符串的“1”和数字1是不同
-
slice() 截取Array的一部分,返回一个新数组,类似于String中的substring
-
push() , pop() 尾部
push():压入到尾部 pop():弹出尾部的一个元素
-
unshift() , shift() 头部
unshift:压入到头部 shift:弹出头部的一个元素
-
排序sort()
["B","C","A"] arr.sort() ["A","B","C"]
-
元素反转 reverse()
["A","B","C"] arr.rever() ["C","B","A"]
-
concat() 拼接两个数组,返回一个新的数组,原数组不会改变
["C","B","A"] arr.concat([1,2,3]) ["C","B","A",1,2,3] arr ["C","B","A"]
注意:concat () 并没有修改数组,只是会返回一个新的数组
-
连接符 join
打印拼接数组,使用特定的字符串连接
["C","B","A"] arr.join('-') "C-B-A"
-
多维数组
arr = [[1,2],[3,4],["5","6"]]; arr[1][1] 4
数组:存储数据(如何存,如何取,方法都可以自己实现!)
对象
若干个键值对
var 对象名 = {
属性名:属性值,
属性名:属性值,
属性名:属性值
}
//定义了一个person对象,它有四个属性!
var person = {
name:"fengzi",
age:3,
email:26556455@qq.com,
score:0
}
js中对象,{…}表示一个对象,键值对描述属性 xxxx: xxxx,多个属性之间使用逗号隔开,最后一个属性不加逗号!
JavaScript中的所有的键都是字符串,值是任意对象!
-
对象赋值
person.name = "jiagnhu" "jianghu" person.name "jianghu"
-
使用一个不存在的对象属性,不会报错!undefined
Person.haha undefined
-
动态的删减属性,通过delete删除对象的属性
delete person.name true person
-
动态的添加属性,直接给新的属性添加值即可
person.haha = "haha" "haha" person
-
判断属性值是否在这个对象中!xxx in xxx!
'age' in person true //继承 'toString' in person true
-
判断一个属性是否是这个对象自身拥有的 hasOwnProperty()
person.hasOwnProperty('toString') false person.hasOwnProperty('age') true
流程控制
- if判断
var age = 3;
if (age>3){//第一个判断
alert("haha");
}else if(age<5){//第二个判断
alert("kuwa");
}else{
alert("kuwa");
}
- while循环,避免程序死循环
var age = 3;
while (age<100){
age = age + 1;
console.log(age);
}
do{
age = age + 1;
console.log(age);
}while (age<100)
- for循环
for (let i = 0; i < 100; i++) {
console.log(i)
}
- forEach循环
var age = [12,3,12,3,12,3,12,31,23,123];
//函数
age.forEach(function (value){
console.log(value)
})
- for…in
//num是索引
for(var num in age){//假设不知道age里有多少的值的时候,这样遍历
console.log(age[num])
}
Map 和 Set
ES6的新特性
- Map
//ES6
//学生的成绩,学生的名字 Map
// var names = ["tom","jack","haha"];
// var scores = [100,90,80];
let map = new Map([['tom',100],['jack',90],['haha',80]]);
let name = map.get('tom');//通过key获得value
map.set('admin',123456);//新增或修改
map.delete("tom"); //删除
- Set:无序不重复的集合
var set = new Set([3,1,1,1,1]);//set可以去重复此时里面只有3和1
set.delete(1);//删除1这个值。
set.add(2);//添加2这个值。
set.has(3);//判断3这个值在不在集合中
iterator
ES6的新特性
- 遍历数组
//通过for of 能够遍历到数组中的值 / for in 遍历的是下标
var arr = [3,4,5]
for (var x of arr){
console.log(x)
}
- 遍历Map
var map = new Map([['tom',100],['jack',90],['haha',80]]);
for (var s of map){
console.log(s);
}
- 遍历set
var set = new Set([5,6,7]);
for(var s of set){
console.log(s)
}
函数
定义函数
- 绝对值函数
function abs(x){
if(x>=0){
return x;
}else{
return -x;
}
}
一旦执行到return 代表函数结束,返回结果!
如果没有执行return,函数执行完也会返回结果,结果就是undefined
定义方式二
var abs = function(x){
if(x>=0){
return x;
}else{
return -x;
}
}
function(x){…}这是一个匿名函数,但是可以把结果赋值给abs,通过abs就可以调用函数!方式一和方式二等价!
调用函数
abs(10)//10
abs(-10)//10
参数问题:JavaScript 可以传任意个参数,也可以不传递参数
参数进来是否存在的问题?假设不存在参数,如何规避?
var abs = function(x){
//手动抛出异常来判断
if (typeof x!=='number'){
throw 'Not a number'
}
if(x>=0){
return x;
}else{
return -x;
}
}
arguments
arguments是一个js免费赠送的关键字:
代表,传递进来的所有的参数,是一个数组!
var abs = function(x){
console.log("x=>"+x);
for(var i = 0;i<arguments.length;i++){
console.log(arguments[i]);
}
if(x>=0){
return x;
}else{
return -x;
}
}
问题:arguments包含所有的参数,我们有时候想使用多余的参数来进行附加操作,需要排除已有的参数~
rest
ES6引入的新特性,获取除了已经定义的参数之外的所有参数~
function aaa(a,b,...rest){
console.log("a=>"+a);
console.log("b=>"+b);
console.log(rest);
}
rest参数只能写在最后面,必须用…标识。
变量的作用域
在JavaScript中,var定义变量实际是有作用域的。
假设在函数体中声明,则在函数体外不可以使用。
function qj(){
var x = 1;
x = x + 1;
}
x = x + 2;//Uncaught ReferenceError: x is not definedat
如果两个函数使用了相同的变量名,只要在函数内部,就不冲突
function qj(){
var x = 1;
x = x + 1;
}
function qj1(){
var x = 'abc';
x = x + 1;
}
内部函数可以访问外部函数的成员,反之则不行
function qj(){
var x = 1;
//内部函数可以访问外部函数的成员,反之则不行
function qj1(){
var y = x + 1;
}
var z = y + 1;//Uncaught ReferenceError: y is not defined
}
假设,内部函数变量和外部函数,重名!
JavaScript中函数查找从自身函数开始,由"内"向“外”查找。假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。
function qj(){
var x = 1;
function qj1(){
var x = 'A';
console.log('inner'+x);//innerA
}
console.log('outer'+x)//outer1
qj1()
}
提升变量的作用域
function qj1(){
var x = "x" + y;
console.log(x);
var y = 'y';
}
结果:xundefined
说明:js执行引擎,自动提升了Y的声明顺序,但是不会提升变量y的赋值的顺序。
function qj1(){
var y;
var x = "x" + y;
console.log(x);
y = 'y';
}
这个是在JavaScript建立之初就存在的特性。养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护
全局变量
//全局变量
x = 1;
function f(){
console.log(x);
}
f();
console.log(x);
全局对象 window
var x = "xxx";
alert(x);
alert(window.x);//默认所有的全局变量,都会自动绑定在window对象下;
alert()这个函数本身也是一个 window 变量
var x = "xxx";
window.alert(x);
var old = window.alert;
//old(x)
window.alert = function (){
} ;
//发现alect()失效了
window.alert(1123);
//恢复
window.alert = old;
window.alert(456);
JavaScript实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,就会报错 RefrenceError。