一、JavaScript简介
1、特点与用途:
JavaScript一般用来编写客户端脚本,来为html页面添加交互行为,是前台语言,而不是后台语言(node.js除外)
特点:
#1、解释执行(浏览器就是解释器):事先不编译、逐行执行、无需严格的变量声明
#2、简单易用:可以使用任何文本编辑器工具编写,只需要浏览器就可以执行程序
#3、基于对象:内置大量现成对象,编写少量程序可以完成目标
2、JavaScript组成
#1、ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等
#2、文档对象模型(DOM)Document object model:操作网页上的元素的API(如让盒子移动、变色、轮播图等)
#3、浏览器对象模型(BOM)Broswer object model:操作部分浏览器功能的API(如让浏览器自动滚动)
3、ECMAScript和JavaScript的关系
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,所以ECMAScript可以理解为是javascript的一个标准,而javascript是ECMA-262标准的实现和扩展。
二、JavaScript引入方式
1、方式一
<script>
//JS代码
</script>
2、方式二
<script src="xxx.js"></script>
三、JavaScript语法规范
#1、JavaScript对换行、缩进、空格不敏感
ps:每一条语句末尾要加上分号,虽然分号不是必须加的,但是为了程序今后要压缩,如果不加分号,压缩之后就不能运行
#2、所有的符号,都是英文的(分号、引号等)
#3、JavaScript的注释:
- 单行注释:
//注释
- 多行注释:
/*
多行注释一
多行注释二
...
*/
四、变量
1、声明变量的语法
// 1、先声明后定义
var name; //声明变量时无需指定类型,变量那么可以接收任意类型
name="jason";
// 2、声明立刻定义
var age=18;
PS:JavaScript是一种弱类型的动态语言
2、变量名命名规范
#1、由数字、字母、下划线、$ 组成,但是不能是纯数字,也不能以数字开头
#2、严格区分大小写
#3、不能包含关键字和保留字(如 abstract、boolean、byte、char、class、const、debugger、double、enum、export、extends、final、float、goto、implements、import、int、interface、long、native、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile等)
#4、推荐驼峰体命名法:有多个有意义的单词组成名称的时候,第一个单词的首字母小写,其余的单词首字母大写
#5、匈牙利命名:根据数据类型的首字符作为前缀
3、ES6中的let
ES6之前js没有块级作用域,ES6新增了let命令,用于声明变量(声明的变量属于块级作用域),流程控制语句的{}就是块级作用域,其用法类似于var,但是所声明的变量只能在let命令所在的代码内有效
例如: for循环的计数器就很适合使用let命令。
for(let i=1;i<5;i++){}
4、常量
ES6中新增const 来声明常量,一旦声明,不能改变
const PI =3.1415926
PI=3 //TypeError: "PI" is read-only
五、数据类型与内置方法
js是动态语言:变量里面能够存储数字、字符串等。变量会自动的根据存储内容的类型不同,来决定自己的类型。
1、数值(number)
js不区分整型和浮点型,只有一种数字类型:number
var x= 3;
var y= 1.2;
var z= 1.23e5;
var a= 5e-2;
var n= NaN; //typeof n结果就是"number"
四舍五入
var num = 1.3456
num.toFixed(2) //"1.35"
字符串类型转成数字
#字符串类型转成number
parseInt("123") //返回123
#NaN属性是代表非数字值的特殊值,用于指示某个值不是数字
parseInt("AAA") // 返回NaN
# 带有自动净化的功能;只保留字符串开头的数字,后面的中文自动消失。例如:
parseInt("24科比"); // 返回24
#只会去末尾的中文,不会去开头的
parseInt("科比24"); // 返回NaN
#字符串中的数字转浮点数
parseInt("1.23"); // 返回1
parseFloat("1.234"); // 返回1.234
#自动带有截断小数的功能:取整,不四舍五入
var a = parseInt("1.3") + parseInt("2.5"); // a=3
var a = parseFloat("1.3") + parseFloat("2.5"); // a=3.8
数字类型转成字符串
# 数字转换成字符串类型
var x=10;
var y="20";
var z=x+y; // z="1020"
typeof z; //string
#数字转成字符串类型
var m=123;
var n=string(m);
var a = 123;
var b = a.toString()
2、字符串(String)
var a = "hello";
var b = "world";
var c = a + b;
console.log(c); //得到Helloworld
常用方法:
方法 | 描述 |
.length | 返回长度 |
.trim() | 移除空白 |
.trimLeft() | 移除左边的空白 |
.trimRight() | 移除右边的空白 |
.charAt(n) | 返回第n个字符 |
.concat(value,…) | 拼接,拼接字符串通常使用"+"号 |
.indexOf(substring,start) | 子序列位置 |
.substring(from,to) | 根据索引获取子序列 |
.slice(start,end) | 切片 |
.toLowerCase() | 小写 |
.toUpperCase() | 大写 |
.split(delimiter,limit) | 分割 |
slice和substring的区别:
string.slice(start, stop)和string.substring(start, stop):
# 两者的相同点:
如果start等于end,返回空字符串
如果stop参数省略,则取到字符串末
如果某个参数超过string的长度,这个参数会被替换为string的长度
- substirng()的特点:
如果 start > stop ,start和stop将被交换
如果参数是负数或者不是数字,将会被0替换
- silce()的特点:
如果 start > stop 不会交换两者
如果start小于0,则切割从字符串末尾往前数的第abs(start)个的字符开始(包括该位置的字符)
如果stop小于0,则切割在从字符串末尾往前数的第abs(stop)个字符结束(不包含该位置字符)
补充:
ES6中引入了模板字符串(template string),是增强版的字符串,用反引号(`)标识,用途:
#1、完全可以当做普通普通字符串使用
var msg=`my name is jason`
#2、也可以用来定义多行字符串
var msg = `
name:jason
age:18
`
#3、可以在字符串中嵌入变量
var name = "jason";
var age = 18;
var msg = `my name is $(name), my age is $(age)`;
注意:
如果模板字符串中需要使用反引号,则要在其前面使用反斜杠转义
3、布尔值(Boolean)
var a = true;
var b = false;
任何数据类型都可以转换成boolean类型:空字符串、0、null、undefined、NaN都是False
特殊的: Boolean([])值为true
4、null和undefined
- null表示值是空,一般用在需要指定或者清空一个变量时才会使用,如name=null
- undefined表示当声明一个变量但是未初始化时,该变量的默认值是undefined,
另外函数无明确的返回值时,也会返回undefined
null表示变量的值是空,undefined则表示只声明了变量。但还没有赋值
5、常用内置对象
JavaScript中的所有事物都是对象:字符串、数值、数组、函数...
此外,JavaScript还提供多个内建对象,如 Array,Date,Math等等
对象只是带有属性和方法的特殊数据类型
5.1 数组对象 Array
数组对象的作用是:使用单独的变量名来存储一些列的值,类似于python中的列表
var x = ["jason","hello"];
console.log(x[0]); //输出"hello"
常用的方法:
方法 | 描述 |
.length | 数租的大小 |
.push(ele) | 尾部追加元素 |
.pop() | 获取尾部的元素 |
.unshift(ele) | 头部插入元素 |
.shift() | 头部移除元素 |
.slice() | 切片 |
.reverse() | 反转 |
.join(seq) | 将数组元素连接成字符串 |
.concat(val, …) | 连接数组 |
.sort() | 排序 |
.forEach() | 将数组的每个元素传递给回调函数 |
.splice() | 删除元素,并向数组添加新元素 |
.map() | 返回一个数组元素调用函数处理后的值的新数组 |
关于sort()需要注意的是:
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,更精确地说,是按照字符编码的顺序进行排序。
示例:
var arr = [123,9,1211,11];
arr.sort() //得到数组[11,1211,123,9]
如果想按照其他标准进行排序,就需要提供比较函数,该函数应该具有两个参数a和b,接受传入的a和b,执行函数体代码,然后返回一个值用于说明a和b的大小
返回值<0:代表a小于b
返回值=0:代表a等于b
返回值>0:代表a大于b
注意:
var x="5";
var y="3";
res = x - y; //res=2
typeof res //"number"
示例:
function sortNumber(a,b){
return a-b
}
var arr = [123,9,1211,11]
arr.sort(sortNumber) // [9,11,123,1211]
关于遍历数组中的元素,可以使用下面的方式:
var arr = [11,22,33,44];
for (var i=0;i<arr.length;i++) {
console.log(i);
}
forEach()
语法:
forEach(function(currentValue,index,arr), thisValue)
参数:
参数 | 描述 |
function(currentValue,index,arr) | 必需,数组中的每个元素要调用的函数: 函数的参数: - currentValue:必需。当前元素 - index:可选。当前元素的索引值。 - arr:可选。当前元素所属的数组对象。 |
thisValue | 可选。传递给函数的值一般用"this"值 如果这个参数为空,"undefined"会传递给"this"值 |
splice()
语法:
splice(index, howmany, item1,…,itemX)
参数:
参数 | 描述 |
index | 必需。整数,规定添加/删除项目的位置,使用负数可以从数组结尾处规定位置。 |
howmany | 可选。表示要删除的项目数量(index对应的值也算一个)。如果不指定默认值为0,代表不会删除项目 |
item1, …, itemX | 可选。向数组添加的新项目。 |
map()
语法:
map(function(currentValue, index, arr), thisValue)
参数同forEach
5.2 Date日期对象
创建日期对象只有构造函数一种方式,使用new关键字
//方法一:不指定参数
var d1=new Date();
console.log(d1.toLocaleString());
//方式2:参数为日期字符串
var d2 = new Date("2020/09/21 11:11:11");
console.log(d2.toLocaleString());
var d3 = new Date("20/09/21 11:11:11");
console.log(d3.toLocaleString());
//方式3:参数为毫秒数
var d4 = new Date(7000);
console.log(d4.toLocaleString());
console.log(d4.toUTCString());
//方式4:参数为:年,月,日,时,分,秒,毫秒
var d5 = new Date(2020,9,21,20,12,30,500);
console.log(d5.toLocaleString()); //毫秒并不直接显示
常用的方法:
方法 | 描述 |
getDate() | 根据本地时间返回指定日期对象的月份中的第几天(1-31) |
getMonth() | 根据本地时间返回指定日期对象的月份(0-11) |
getFullYear() | 根据本地时间返回指定日期对象的年份(四位数年份时返回四位数字) |
getDay() | 根据本地时间返回指定日期对象的星期中的第几天(0-6) |
getHours() | 根据本地时间返回指定日期对象的小时(0-23) |
getMinutes() | 根据本地时间返回指定日期对象的分钟(0-59) |
getSecond() | 根据本地时间返回指定日期对象的秒数(0-59) |
getMilliseconds() | 根据本地时间返回指定日期对象的毫秒数 |
getTime() | 返回累计毫秒数(从1970/1/1午夜) |
5.3 Math对象
方法 | 含义 |
Math.floor() | 向下取整(去一),如5.1取整为5 |
Math.ceil() | 向上取整(进一),如5.1取整为6 |
Math.max(a,b) | 求a和b的最大值 |
Math.min(a,b) | 求a和b的最小值 |
Math.random() | 随机数,默认去01之间的随机数,若想求minmax之间的数,公式为min+Math.random()*(max-min) |
5.4 JSON对象
# JSON格式的字符串转成对象
var str1 = '{"name":"jason", "age":18}';
var dic1 = JSON.parse(str1);
console.log(obj1.name);
console.log(obj1["name"];
# 对象转成JSON字符串
var dic2 = {"name":"cc", "age":20};
var str2 = JSON.stringify(dic2);
5.5 RegExp对象
#1、创建正则对象的方式1
//参数1 正则表达式
//参数2 匹配模式:常用g(全局匹配;找到所有匹配,而不是在第一个匹配后停止)和i(忽略大小写)
//注意:正则放到引号内,{}内的逗号后面不要加空格
示例:
var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,11}$")
reg1.test("jason_123"); //true
#2、创建正则对象的方式2
var reg2 = /^[a-zA-Z][a-zA-Z0-9_]{5,11}$/; //不要加引号
reg2.test("jason_123");
#3、String对象与正则结合的4个办法
var s1 = "hello world";
s1.match(/l/g) //["l", "l", "l"] 可以将所有“l”匹配到
s1.search(/l/g) //2
s1.split(/ /) //["hello", "world"]
s1.replace(/l/g,"L") //"heLLo worLd"
#4、匹配模式g与i
var s2 = "name:Ec age:18";
s2.repalce(/e/, '乖') //"nam乖:Ec ag乖:18"
s2.repalce(/e/g, '乖') //"nam乖:Ec ag乖:18"
s2.repalce(/e/gi, '乖') //"nam乖:乖c ag乖:18"
#5、注意:
- ① 如果regExpObject带有全局标志g,test()函数不是从字符串的开头开始查找,而是从属性regExpObject.lastIndex所指定的索引处开始查找。
- ② 该属性值默认为0,所以第一次仍然是从字符串的开头查找。
- ③ 当找到一个匹配时,test()函数会将regExpObject.lastIndex的值改为字符串中本次匹配内容的最后一个字符的下一个索引位置。
- ④ 当再次执行test()函数时,将会从该索引位置处开始查找,从而找到下一个匹配。
- ⑤ 因此,当我们使用test()函数执行了一次匹配之后,如果想要重新使用test()函数从头开始查找,则需要手动将regExpObject.lastIndex的值重置为 0
- ⑥ 如果test()函数再也找不到可以匹配的文本时,该函数会自动把regExpObject.lastIndex属性重置为 0
# 示例:
var reg3 = /cc/g; //undefined
reg3.lastIndex //0
reg3.test('cc'); //true
reg3.lastIndex //2
reg3.test('cc'); //false 从2的位置开始匹配,本次匹配失败
reg3.lastIndex //0 匹配不成功,lastIndex归为0
reg3.test("cc"); //true
#6、注意2:
当我们不参加参数调用RegExpObj.test()方法时,相当于执行RexExpObj.test("undefined"),并且/undefined/.test()默认返回true
var reg4 = /^undefined$/;
reg4.test(); //返回true
reg4.test(undefined); //返回False
reg4.test("undefined"); //返回true
5.6 自定义对象
#一、创建对象的几种方式
1、使用object或者对象字面量创建对象
2、工厂模式创建对象
3、构造函数模式创建对象
4、原型模式创建对象
#1.1 使用Object或者对象字面量创建对象
js中最基本的创建对象的方式:
var student = new Object();
student.name = "jason";
student.age = 20;
这样一个student对象就创建完成了,拥有两个属性name和age,值分别为"jason"和20
或者这样:
var student1 = {
name :"jason",
age : 20
};
但是这样创建同类的对象时,需要重复代码
#1.2 工厂模式创建对象
js中没有类,但可以使用函数将对象创建的过程封装起来以便于重复调用,同时给出特定接口来初始化对象
function createStudent(name,age) {
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
var student1 = createStudent('jason',20);
var student2 = createStudent('cc',20);
...
六、运算符
算术运算符
+ 、 - 、 * 、 / 、 % 、 ++ 、 --
比较运算符
> 、>= 、< 、<= 、!= 、== 、=== 、!==
注意:
1 == "1" //true
1 === "1" //false
逻辑运算符
&& 与
|| 或
! 非
赋值运算符
= 、 += 、-= 、*= 、/=
七、流程控制
1、 if->else
var age = 20;
if(age > 18){
console.log("old");
}else {
console.log("young");
}
2、if ->else if -> else
var age = 20;
if(age > 18){
console.log("old");
}else if(age == 18){
console.log('nice')
}
else {
console.log("young");
}
3、switch
switch中的case子句通常会加break语句,否则程序hi继续执行后续case中的语句
var d1 = new Date().getDay();
switch (d1) {
case 0:
console.log("星期天");
break;
case 6:
console.log("星期六");
break;
default:
console.log("工作日")
}
4、for
for (let i=1;i<=3;i++){
console.log(i);
}
5、while
var i=0;
while (i<=3){
console.log(i);
i++;
}
6、三元运算
格式:
var 变量 = 条件? 值1:值2
如果满足条件:变量=值1,否则变量=值2
var x=1;
var y=2;
var z = x>y?x:y // 如果x>y则z=x,否则z=y
八、函数
1、函数的定义与调用(与python类似)
// 无参函数
function f1() {
console.log("hello world");
}
f1();
// 有参函数
function f2(a,b) {
console.log(arguments); //内置的arguments对象
console.log(arguments.length);
console.log(arguments[0],arguments[1]);
console.log(a,b);
};
f2(10,20);
// 带返回值的函数(函数只能由一个返回值,如果想要返回多个值,只能放在数组或者对象中返回)
function sum(a,b){
return a+b;
}
sum(3,4);
//匿名函数
var sum = function(a,b){
return a+b;
}
sum(1,2);
//立即执行函数
(function(a,b){
return a+b;
})(1,2);
2、函数中的arguments参数
function add(a,b){
console.log(a+b);
console.log(arguments.length)
}
add(1,2)
输出结果:
3
2
3、函数的全局变量和局部变量
# 局部变量
在JavaScript中函数内部声明的变量(使用var)是局部变量,所以只能在函数内部访问(该变量的作用域是函数内部),只要函数运行完毕,局部变量就会被删除
# 全局变量
在函数外声明变量时全局变量,网页上的所有脚本和函数都能访问它。
# 变量生存周期
JavaScript变量的生命期从他们被声明的时间开始。
局部变量会在函数运行以后被删除
全局变量会在页面关闭后被删除
4、作用域
首先在函数内部找,找不到就去外层函数找,逐步找到最外层,
函数作用域关系是在定义阶段就固定死的,与调用位置无关。
示例:
var name = "jason";
function f() {
var name = 'jack';
function inner(){
var name = 'jacky';
console.log(name);
}
inner();
}
f(); //jacky
5、JavaScript中的变量提升和函数提升
5.1 在js中只有两种作用域
# 1、全局作用域
# 2、函数作用域
在ES6之前,js是没有块级作用域的
5.2 什么是变量提升?
在js中,代码的执行分为两步:1、解析,2、一步一步执行
那么变量提升就是变量声明会被提升到作用域的最顶上去,(也就是说该变量不管在作用域什么地方声明,都会被提升到作用域的最顶上去)
5.3 什么是函数提升?
注意:函数声明式,会将函数的声明和定义一起提升到作用域的最顶上去。
总结:
#1、所有的声明都会提升到作用域的最顶上去
#2、同一个变量只会声明一次,其他的会被忽略掉。
#3、函数声明的优先级高于变量声明的优先级,并且函数声明和函数提升的部分一起被提升