一、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、函数声明的优先级高于变量声明的优先级,并且函数声明和函数提升的部分一起被提升