参考资料:https://blog.csdn.net/qq_38490457/article/details/109257751
略。
一个完整的JavaScript实现应该由以下三个部分构成:ECMScript + DOM + BOM。
标签引用:在HTML中在script标签中就可以编写JavaScript代码
<script>
alert("Hello,World!");
</script>
文件引用:在一个单独的js文件中也可以编写JavaScript代码,然后在HTML文件中使用script标签进行引用
<script src="main.js"></script>
一个.html文件中可以有多个script标签,多个script标签自上而下顺序执行;
但一个script标签只能专心地做一件事件,即一个script标签要么用于引入外部 .js文件,要么直接在页面中写js代码
注意语法规范:注意每一行js代码结束的位置都要加分号 ;
使用JavaScript向页面输出一句话:
<script>
document.write("Hello,World!");
</script>
使用JavaScript向控制台输出一句话:
<script>
console.log("输出一条日志");//最常用
console.info("输出一条信息");
console.warn("输出一条警告");
console.error("输出一条错误");
</script>
使用JavaScript向弹出窗口输出一句话:
<script>
alert("Hello,World!");
</script>
// 注释内容
/* 注释内容 */
标识符,就是指给变量、函数、属性或函数的参数起名字。
标识符命名规则:
字面量实际上就是一些固定的值,字面量都是不可以改变的。
由于字面量不是很方便使用,所以在JavaScript中很少直接使用字面量,使用的而是变量。
值可以被修改的叫做变量。JavaScript 变量是存储数据值的容器。
var
关键字声明一个变量。<script>
var num = 10;
num = "hello";
/* 以上操作合法,但不推荐 */
</script>
JavaScript中一共有5种基本数据类型:
这5种之外的类型都称为Object,所以总的来看JavaScript中共有六种数据类型。
使用typeof操作符可以用来检查一个变量的数据类型。
使用方式:
typeof 数据
String用于表示一个字符序列,即字符串。字符串需要使用 单引号 或 双引号 括起来。
Number 类型用来表示整数和浮点数,最常用的功能就是用来表示10进制的整数和浮点数。
特殊的数字:
其它的进制:
注意:使用typeof检查一个Number类型的数据时(包括NaN 和 Infinity),会返回"number"。
布尔型也被称为逻辑值类型或者真假值类型。
布尔型只能够取真(true)和假(false)两种数值。除此以外, 其它的值都不被支持。
在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined。
undefined值实际上是由null值衍生出来的,所以如果比较undefined和null是否相等,会返回true。
从语义上看null表示的是一个空的对象,所以使用typeof检查null会返回一个Object。
<script>
console.log(undefined == null)
console.log(undefined === null)
console.log(typeof null);
</script>
强制类型转换指将一个数据类型强制转换为其它的数据类型。一般是指,将其它的数据类型转换为String、Number、Boolean。
将其它数值转换为字符串有三种方式:toString()、String()、 拼串。
调用被转换数据类型的toString()
方法,该方法不会影响到原变量,它会将转换的结果返回,但是注意:null和undefined这两个值没有toString()方法,如果调用它们的方法,会报错。
<script>
var a = 123;
console.log(a);
console.log(typeof a);
a = a.toString();
console.log(a);
console.log(typeof a);
</script>
调用String()
函数,并将被转换的数据作为参数传递给函数,使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法,但是对于null和undefined,就不会调用toString()方法,它会将 null 直接转换为 “null”,将 undefined 直接转换为 “undefined”。
有三个函数可以把非数值转换为数值:Number()、parseInt() 和parseFloat()。Number()可以用来转换任意类型的数据,而后两者只能用于转换字符串。
这种方式专门用来对付字符串,parseInt() 把一个字符串转换为一个整数
这种方式专门用来对付字符串,parseFloat() 把一个字符串转换为一个浮点数
注意:如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后再操作
将其它的数据类型转换为Boolean,只能使用Boolean()函数。
运算符也叫操作符,通过运算符可以对一个或多个值进行运算并获取运算结果。
比如:typeof就是运算符,可以来获得一个值的类型,它会将该值的类型以字符串的形式返回(number string boolean undefined object)
算术运算符用于表达式计算。
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取模(求余数) |
++ | 自增 |
- - | 自减 |
自动数据类型转换:将不同的数据类型混合进行算数运算时,会自动进行数据类型转换。
关系运算符在逻辑语句中使用,以测定变量或值是否相等。
关系运算符得到的值最后一定是布尔值。
运算符 | 描述 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
== | 等于 |
=== | 恒等于 |
!= | 不等于 |
!== | 恒不等 |
赋值运算符用于给 JavaScript 变量赋值。
=、+=、-=、*=、/=、%=
逻辑运算符用于测定变量或值之间的逻辑。
&&、||、!
&&可以对符号两侧的值进行与运算并返回结果,运算规则如下:
||可以对符号两侧的值进行或运算并返回结果,运算规则如下:
!可以用来对一个值进行非运算,所谓非运算就是对一个布尔值进行取反操作,true变false,false变true,运算规则如下:
比较运算符用来比较两个值是否相等,如果相等会返回true,否则返回false。
==
来做相等运算!=
来做不相等运算===
来做全等运算!==
来做不全等运算语法:variablename=(condition)?value1:value2;
执行流程:如果condition为true,则执行语句1,并返回执行结果,如果为false,则执行语句2,并返回执行结果。
使用逗号可以在一条语句中执行多次操作。
比如:var num1=1, num2=2, num3=3;
使用逗号运算符分隔的语句会从左到右顺 序依次执行。
语句是一个程序的基本单位,JavaScript的程序就是由一条一条语句构成的,每一条语句使用;
结尾。
代码块是在大括号 {}
中所写的语句,以此将多条语句的集合视为一条语句来使用。
例如:
{
var a = 123;
a++;
alert(a);
}
我们一般使用代码块将需要一起执行的语句进行分组,需要注意的是,代码块结尾不需要加 分号。
条件语句是通过判断指定表达式的值来决定执行还是跳过某些语句,最基本的条件语句:
单分支语句:if…else
双分支语句:if…else if ... else
三目运算符:表达式1 ? 表达式2 : 表达式3;
可以看做是对双分支语句的简写。
先计算表达式1,然后进行判断。如果表达式1的值为true,执行表达式2;否则,执行表达式3。
多分支语句
多分支switch…case
语句
switch语句更适用于多条分支使用同一条语句的情况。
语法格式:
switch (语句) {
case 表达式1:
语句...
case 表达式2:
语句...
default:
语句...
}
注意:需要注意的是一旦符合case的条件程序会一直运行到结束,所以我们一般会在case中添加break作为语句的结束。
循环语句和条件语句一样,也是基本的控制语句,只要满足一定的条件将会一直执行,最基本的循环语句:
while
while(条件表达式){
语句...
}
do…while
do{
语句...
}while(条件表达式);
for
for(初始化表达式 ; 条件表达式 ; 更新表达式){
语句...
}
break
:结束最近的一次循环,可以在循环和switch语句中使用。continue
:结束本次循环,执行下一次循环,只能在循环中使用。Object类型,我们也称为一个对象,是JavaScript中的引用数据类型。它是一种复合值,它将很多值聚合到一起,可以通过名字访问这些值。
对象也可以看做是属性的无序集合,每个属性都是一个名/值对。对象除了可以创建自有属性,还可以通过从一个名为原型的对象那里继承属性。
除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。
创建对象有两种方式:
第一种方式:
var person = new Object();
person.name = "孙悟空";
person.age = 18;
console.log(person);
第二种方式:
var person = {
name: "孙悟空",
age: 18
};
console.log(person);
访问属性的两种方式:
第一种方式:使用 . 来访问
对象.属性名
第二种方式:使用 [] 来访问
对象[‘属性名’]
删除对象的属性可以使用delete关键字,格式如下:
delete 对象.属性名;
枚举遍历对象中的属性,可以使用for … in语句循环,对象中有几个属性,循环体就会执行几次。
语法格式:
for (var 变量 in 对象) {
}
JavaScript中的变量可能包含两种不同数据类型的值:基本数据类型和引用数据类型。
JavaScript中一共有5种基本数据类型:String、Number、 Boolean、Undefined、Null。
基本数据类型的比较是值的比较,也就是只要两个变量的值相等,我们就认为这两个变量相等。
引用类型的值是保存在内存中的对象。
当一个变量是一个对象时,实际上变量中保存的并不是对象本身,而是对象的引用。
当从一个变量向另一个变量复制引用类型的值时,会将对象的引用复制到变量中,并不是创建一个新的对象。
这时,两个变量指向的是同一个对象。 因此,改变其中一个变量会影响另一个。
JavaScript在运行时数据是保存到栈内存和堆内存当中的。
简单来说栈内存用来保存变量和基本类型,堆内存是用来保存对象。
我们在声明一个变量时,实际上就是在栈内存中创建了一个空间用来保存变量。
如果是基本类型则在栈内存中直接保存,如果是引用类型则会在堆内存中保存,但是引用类型的引用还是存在栈内存中的。
函数是由一连串的子程序(语句的集合)所组成的,可以被外部程序调用,向函数传递参数之后,函数可以返回一定的值。
通常情况下,JavaScript代码是自上而下执行的,不过函数体内部的代码则不是这样。如果只是对函数进行了声明,其中的代码并不会执行,只有在调用函数时才会执行函数体内部的代码。
这里要注意的是JavaScript中的函数也是一个对象,使用typeof检查一个函数对象时,会返回function。
使用 函数对象 (new
)来创建一个函数(几乎不用)
var 函数名 = new Function("执行语句");
使用 函数声明 (function
关键字)来创建一个函数(比较常用)
function 函数名(形参1,形参2,...,形参N) {
语句...
}
使用 函数表达式 来创建一个函数(比较常用)
var 函数名 = function(形参1,形参2,...,形参N) {
语句....
}
函数名(参数1,参数2...);
每一个函数内部都有一个arguments,这是系统内置的。
arguments是用来存储实参的。所以可以用 arguments 对象检测函数的参数个数,引用属性 arguments.length 即可。
<script>
function howManyArgs(){
alert(arguments.length)
}
howManyArgs(); //结果为:0
howManyArgs("123"); //结果为:1
howManyArgs(4, "hello", 7) //结果为3
</script>
也可用 arguments[下标] 的方式访问某一项数据,下标从0开始。
在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
与其他程序设计语言不同,ECMAScript不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数都可以接受任意个数的参数。
<script>
function sun(){ //函数里面没有规定参数
var res = 0;
for ( var i=0; i<arguments.length; i++ ){
res += arguments[i];
}
return res;
}
var num = sum(45, 50, 7); //可以输入任意多个数
alert(num); //结果为:102
</script>
可以使用 return 来设置函数的返回值,return后的值将会作为函数的执行结果返回,可以定义一个变量,来接收该结果。
语法格式:return 值
注意:在函数中return后的语句都不会执行,如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return,则也会返回undefined,return后可以跟任意类型的值
在函数中声明的函数就是嵌套函数,嵌套函数只能在当前函数中可以访问,在当前函数外无法访问。
没有名字的函数就是匿名函数,它可以让一个变量来接收,也就是用 “函数表达式” 方式创建和接收。
例如:
var fun = function () {
alert("我是一个匿名函数");
}
fun();
函数定义完,立即被调用,这种函数叫做立即执行函数,立即执行函数往往只会执行一次。
例如:
(function () {
alert("我是一个匿名函数");
})();
对象的属性值可以是任何的数据类型,也可以是个函数。
如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法,调用这个函数就说调用对象的方法(method)。
注意:方法和函数只是名称上的区别,没有其它别的区别
解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式的不同,this会指向不同的对象
创建多个对象示例:
<script>
// 使用工厂模式创建对象
function createPerson(name, age) {
// 创建新的对象
var obj = new Object();
// 设置对象属性
obj.name = name;
obj.age = age;
// 设置对象方法
obj.sayName = function () {
console.log(this.name);
};
//返回新的对象
return obj;
}
var person1 = createPerson("孙悟空", 18);
var person2 = createPerson("猪八戒", 19);
var person3 = createPerson("沙和尚", 20);
console.log(person1);
console.log(person2);
console.log(person3);
</script>
上述代码好像已经完美的解决了创建多个对象的难题,那我们是不是可以用循环批量创建1000个对象了呢?那我们就来试试:
<script>
// 使用工厂模式创建对象
function createPerson(name, age) {
// 创建新的对象
var obj = new Object();
// 设置对象属性
obj.name = name;
obj.age = age;
// 设置对象方法
obj.sayName = function () {
console.log(this.name);
};
//返回新的对象
return obj;
}
for (var i = 1; i <= 1000; i++) {
var person = createPerson("person" + i, 18);
console.log(person);
}
</script>
这样我们就实现了批量创建对象的功能,至于对象的名称和年龄,我们可以通过名称数组和年龄数组来获取,但这并不是我们本小节的重点,我们就忽略了。
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写,构造函数和普通函数的还有一个区别就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new
关键字来调用。
<script>
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
// 设置对象的方法
this.sayName = function () {
console.log(this.name);
};
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);
console.log(person1);
console.log(person2);
console.log(person3);
</script>
那构造函数是怎么执行创建对象的过程呢?我再来解释一下:
你会发现构造函数有点类似工厂方法,但是它创建对象和返回对象都给我们隐藏了,使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象,称为是该类的实例。
现在,this又出现了一种新的情况,为了不让大家混淆,我再来梳理一下:
我们可以使用 instanceof
运算符检查一个对象是否是一个类的实例,它返回true或false
语法格式:
对象 instanceof 构造函数
在前一节中,我们学习了使用构造函数的方式进行创建对象,但是,它还是存在一个问题,那就是,你会发现,每一个对象的属性不一样这是一定的,但是它的方法似乎好像是一样的,如果我创建1000个对象,那岂不是内存中就有1000个相同的方法,那要是有10000个,那对内存的浪费可不是一点半点的,我们有没有什么好的办法解决,没错,我们可以把函数抽取出来,作为全局函数,在构造函数中直接引用就可以了.
上代码:
但是,在全局作用域中定义函数却不是一个好的办法,为什么呢?
因为,如果要是涉及到多人协作开发一个项目,别人也有可能叫sayName这个方法,这样在工程合并的时候就会导致一系列的问题,污染全局作用域,那该怎么办呢?
有没有一种方法,我只在Person这个类的全局对象中添加一个函数,然后在类中引用?答案肯定是有的,这就需要原型对象了,我们先看看怎么做的,然后在详细讲解原型对象。
<script>
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
}
// 在Person类的原型对象中添加方法
Person.prototype.sayName = function () {
console.log(this.name);
};
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);
person1.sayName();
person2.sayName();
person3.sayName();
</script>
那原型(prototype)到底是什么呢?
我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象,即显式原型,原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
如果函数作为普通函数调用prototype没有任何作用,当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__
(隐式原型)来访问该属性。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。
以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
访问一个对象的属性时,先在自身属性中查找,找到返回, 如果没有,再沿着__proto__这条链向上查找,找到返回,如果最终没找到,返回undefined,这就是原型链,又称隐式原型链,它的作用就是查找对象的属性(方法)。
toString()函数用于将当前对象以字符串的形式返回。该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法,所有主流浏览器均支持该函数。
JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。
类型 | 行为描述 |
---|---|
String | 返回 String 对象的值。 |
Number | 返回 Number 的字符串表示。 |
Boolean | 如果布尔值是true,则返回"true"。否则返回"false"。 |
Object(默认) | 返回"[object ObjectName]",其中 ObjectName 是对象类型的名称。(暂未理解 ) |
Array | 将 Array 的每个元素转换为字符串,并将它们依次连接起来,两个元素之间用英文逗号作为分隔符进行拼接。 |
Date | 返回日期的文本表示。 |
Error | 返回一个包含相关错误信息的字符串。 |
Function | 返回如下格式的字符串,其中 functionname 是一个函数的名称 此函数的 toString 方法被调用: “function functionname() { [native code] }” |
演示:
<script>
// 字符串
var str = "Hello";
console.log(str.toString()); //hello
// 数字
var num = 15.26540;
console.log(num.toString()); //15.2654
// 布尔
var bool = true;
console.log(bool.toString()); //true
// Object
var obj = {
name: "张三",
age: 18
};
console.log(obj.toString()); //[object, Object]
// 数组
var array = ["CodePlayer", true, 12, -5];
console.log(array.toString()); //CodePlayer,true,12,-5
// 日期
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
console.log(date.toString()); //Sun Aug 18 2013 23:11:59 GMT+0800 (中国标准时间)
// 错误
var error = new Error("自定义错误信息");
console.log(error.toString()); //Error: 自定义错误信息
// 函数
console.log(Function.toString()); //function Function() { [native code] }
</script>
如果判断当前对象是否包含指定的属性或方法可以使用 in
运算符来检查。
如果我只想要检查自身对象是否含有某个方法或属性,我们可以使用Object的hasOwnProperty()
方法,它返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
hasOwnProperty()是原型中的方法。
二者区别如下代码演示:
<script>
// 创造一个构造函数
function MyClass() {}
// 向MyClass的原型中添加一个name属性
MyClass.prototype.name = "我是原型中的名字";
// 创建一个MyClass的实例
var mc = new MyClass();
mc.age = 18;
// 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
console.log("age" in mc); //true
console.log("name" in mc); //true
// 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有属性时,才会返回true
console.log(mc.hasOwnProperty("age")); //true
console.log(mc.hasOwnProperty("name")); //false
</script>
实际上,JavaScript语言是通过一种叫做原型(prototype)的方式来实现面向对象编程的。
实现继承有一个最大的好处就是子对象可以使用父对象的属性和方法,从而简化了一些代码。
JavaScript有六种非常经典的对象继承方式,但是我们只学习前三种:
继承有点难理解,先放一放
核心思想: 子类型的原型为父类型的一个实例对象
基本做法:
示例:
垃圾回收(GC:Garbage Collection):就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生的垃圾。
当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作,我们需要做的只是要将不再使用的对象设置null即可。
案例演示:
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);
person1 = null;
person2 = null;
person3 = null;
其他参考链接:https://blog.csdn.net/qq_21428081/article/details/82465801
作用域指一个变量的作用的范围,在JS中一共有两种作用域:
变量的声明提前(变量提升):使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值);
但是如果声明变量时不使用var关键字,则变量不会被声明提前(let、const无变量提升)
函数的声明提前:使用函数声明形式创建的函数 function 函数名(){}
,它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数。
使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用。
多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外),查找变量时就是沿着作用域链来查找的。
查找一个变量的查找规则:
JavaScript 严格模式(strict mode),即在严格的条件下运行。严格模式下不能使用未声明的变量。
通过在脚本或函数的开头添加 "use strict";
来声明严格模式。
在脚本开头进行声明,拥有全局作用域(脚本中的所有代码均以严格模式来执行):
例如为脚本开启严格模式:
<script>
"use strict";
x = 3.14; // 这会引发错误,因为 x 尚未声明
</script>
为函数开启严格模式(把声明放在函数体所有语句之前):
<script>
function f1(){
'use strict';
}
function f2(){
}
</script>
数组也是对象的一种,数组是一种用于表达有顺序关系的值的集合的语言结构,在JavaScript中数组内可以是不同的元素。
数组内的各个值被称作元素,每一个元素都可以通过索引(下标)来快速读取,索引是从零开始的整数。
使用typeof
检查一个数组对象时,会返回object。
[ ]
表示数组)<script>
var arr1 = new Array("hello", 5, 20); //通过 new 创建数组
var arr2 = Array("hello", 5, 20); //省略 new
var arr3 = ["hello", 5, 20]; // 直接通过常量赋值
//以上三种声明方法得到的数组是一样的
</script>
【注】使用第1、2种方法时,如果传入的参数只有一个,并且使数字时,表示直接声明该数组的长度。
<script>
var arr1 = new Array(10); //表示声明了一个长度为10的空数组arr1
var arr2 = Array(10); //表示声明了一个长度为10的空数组arr2
var arr3 = [10]; //表示数组 arr3 中有一个数据,该数据为10
</script>
// for 循环
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// for in 循环
for(j in arr) {
}
其他js遍历数组方式参考链接:http://t.csdn.cn/SEZVg
功能:给数组的末尾添加一个或多个元素
返回值:添加完新元素以后的数组的长度
直接操作原始数组
<script>
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.push("唐僧", "蜘蛛精", "白骨精", "玉兔精");
console.log(arr);
console.log(result);
</script>
功能:从数组末尾取下一个元素
返回值:被取下的元素
直接操作原始数组
功能:从数组的头部取下一个元素
返回值:取下的元素
直接操作原始数组
功能:从数组的头部插入元素
返回值:插入元素后数组的长度
直接操作原始数组
a)拷贝原数组,生成新数组
b)合并数组
返回值:合并后的新数组,原数组不会改变。
【注】就算合并的是数组,数组中的元素会单独拆出来,再进行合并。
<script>
var arr1 = new Array(30,45,66);
var arr2 = new Array(50,78);
var newArr = arr1.concat(arr2, 'hello')
alert(arr1); //输出结果为:30,45,66
alert(newArr); //输出结果为:30,45,66,50,78,hello
alert(newArr.length) //输出结果为:6
</script>
格式:数组.slice(start, end);
功能:可以基于当前数组获取指定区域元素 [star, end),提取出元素生成新数组。
【注】start和end指的是数组的下标,并且不包括下标end;如果不写end则默认截取到末尾;如果传入的参数是负数,则从数组的末尾往前数,-1代表倒数第一个,-2代表倒数第二个。
返回值:生成新数组,原数组不会有任何改变
<script>
var arr1 = new Array(76,98,17,28,10,64,564);
var newArr1 = arr1.slice(2,4);
var newArr2 = arr1.slice(2,-4);
var newArr3 = arr1.slice(-4,-2);
console.log(newArr1);
console.log(newArr2);
console.log(newArr3);
</script>
格式:数组.splice( start, length, 数据1, 数据2, …);
参数:
<script> //增加元素
var arr1 = Array(10,20,30,40);
var newArr = arr1.splice(2,0,'hey',88);
alert(arr1); //输出结果:10,20,hey,88,30,40
alert(newArr); //输出结果为空
</script>
<script>
var arr1 = Array(10,20,30,40);
var newArr = arr1.splice(2,2);
alert(arr1); //输出结果:10,20
alert(newArr); //输出结果:30,40
</script>
功能:将数组中的元素,用传入的拼接符,拼接成一个字符串;如果不指定连接符,则默认使用逗号,
作为连接符
返回值:拼接好的字符串
<script>
var arr = [10,20,30];
var str1 = arr.join('**');
var str2 = arr.join('');
var str3 = arr.join();
console.log(arr);
console.log(str1);
console.log(str2);
console.log(str3);
</script>
格式:数组.reverse( );
功能:该方法用来反转数组(前边的去后边,后边的去前边)
该方法会改变原来的数组,而不会创建新的数组
<script>
var arr = ['hello','hey','hi'];
arr.reverse();
alert(arr); //输出为:hi,hey,hello
</script>
格式:数组.sort( );
功能:sort()会调用toString()方法将数组中的每一项转化成字符串,然后默认会按照Unicode编码进行排序,默认情况下为升序
在原数组上进行排序,不生成副本
【注】即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字进排序时,可能会得到错误的结果。
<script>
var arr = [15,10,1,5];
arr.sort();
console.log(arr); //[1, 10, 15, 5]
</script>
如果想要按照数值的大小进行排序,我们可以在sort()添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数,使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边,浏览器会根据回调函数的返回值来决定元素的顺序,如下:
经过上边的规则,我们可以总结下:
<script>
var arr = [15,10,1,5];
arr.sort(function (a, b) {
return a - b;
});
console.log(arr); //[1, 5, 10, 15]
</script>
该方法可以用来遍历数组.
forEach()方法需要一个函数作为参数,像这种函数,由我们创建但是不由我们调用的,我们称为回调函数。数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素,以实参的形式传递进来,我们可以来定义形参,来读取这些内容,浏览器会在回调函数中传递三个参数:
注:这个方法只支持IE8以上的浏览器,IE8及以下的浏览器均不支持该方法,所以如果需要兼容IE8,则不要使用forEach(),还是使用for循环来遍历数组。
<script>
var arr = ["孙悟空", "猪八戒", "沙和尚"];
arr.forEach(function (value, index, obj) {
console.log(value + " #### " + index + " #### " + obj);
});
</script>
更多关于forEach()用法及使用的坑,参考链接:https://blog.csdn.net/qsj0606/article/details/116004448
call()和apply()这两个方法都是函数对象的方法,需要通过函数对象来调用,当对函数调用call()和apply()都会调用函数执行,在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this,call()方法可以将实参在对象之后依次传递,apply()方法需要将实参封装到一个数组中统一传递,如下演示:
call()方法演示:
function fun(a, b) {
console.log("a = " + a);
console.log("b = " + b);
console.log("fun = " + this);
}
var obj = {
name: "obj",
sayName: function () {
console.log(this.name);
}
};
fun(2, 3);
console.log("===============");
fun.call(obj, 2, 3);
注意:默认fun()函数调用,this指向的是window对象,你可以使用call()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,实参将会依次传递
apply()方法演示:
function fun(a, b) {
console.log("a = " + a);
console.log("b = " + b);
console.log("fun = " + this);
}
var obj = {
name: "obj",
sayName: function () {
console.log(this.name);
}
};
fun(2, 3);
console.log("===============");
fun.apply(obj, [2, 3]);
注意:默认fun()函数调用,this指向的是window对象,你可以使用apply()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,需要制定一个实参数组进行参数传递
在调用函数时,浏览器每次都会传递进两个隐含的参数:
arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度,在调用函数时,我们所传递的实参都会在arguments中保存,比如:arguments.length
可以用来获取实参的长度,我们即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦,例如:
arguments[0]:表示第一个实参
arguments[1]:表示第二个实参
…
它里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象。
arguments对象演示:
<script>
function fun(a, b) {
// 通过下标获取第一个参数
console.log(arguments[0]);
// 通过下标获取第二个参数
console.log(arguments[1]);
// 获取实参的个数
console.log(arguments.length);
// 看看它的函数对象
console.log(arguments.callee);
console.log(arguments.callee == fun);
}
fun("Hello", "World");
</script>
在JavaScript中使用Date对象来表示一个时间,如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间。
<script>
var date = new Date();
console.log(date);
console.log(date.getFullYear()); //获取当前日期对象的年份(四位数字年份)
console.log(date.getMonth()); //获取当前日期对象的月份(0 ~ 11)
console.log(date.getDate()); //获取当前日期对象的日数(1 ~ 31)
console.log(date.getHours()); //获取当前日期对象的小时(0 ~ 23)
console.log(date.getMinutes()); //获取当前日期对象的分钟(0 ~ 59)
console.log(date.getSeconds()); //获取当前日期对象的秒钟(0 ~ 59)
console.log(date.getMilliseconds()); //获取当前日期对象的毫秒(0 ~ 999)
</script>
Math和其它的对象不同,它不是一个构造函数,它属于一个工具类,它里边封装了数学运算相关的属性和方法。
<script>
/*固定值*/
console.log("PI = " + Math.PI);
console.log("E = " + Math.E);
console.log("===============");
/*正数*/
console.log(Math.abs(1)); //可以用来计算一个数的绝对值
console.log(Math.ceil(1.1)); //可以对一个数进行向上取整,小数位只有有值就自动进1
console.log(Math.floor(1.99)); //可以对一个数进行向下取整,小数部分会被舍掉
console.log(Math.round(1.4)); //可以对一个数进行四舍五入取整
console.log("===============");
/*负数*/
console.log(Math.abs(-1)); //可以用来计算一个数的绝对值
console.log(Math.ceil(-1.1)); //可以对一个数进行向上取整,小数部分会被舍掉
console.log(Math.floor(-1.99)); //可以对一个数进行向下取整,小数位只有有值就自动进1
console.log(Math.round(-1.4)); //可以对一个数进行四舍五入取整
console.log("===============");
/*随机数*/
//Math.random():可以用来生成一个0-1之间的随机数
//生成一个0-x之间的随机数:Math.round(Math.random()*x)
//生成一个x-y之间的随机数:Math.round(Math.random()*(y-x)+x)
console.log(Math.round(Math.random() * 10)); //生成一个0-10之间的随机整数
console.log(Math.round(Math.random() * (10 - 1) + 1)); //生成一个1-10之间的随机整数
console.log("===============");
/*数学运算*/
console.log(Math.pow(12, 3)); //Math.pow(x,y):返回x的y次幂
console.log(Math.sqrt(4)); //Math.sqrt(x) :返回x的平方根
</script>
在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
但是注意:我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果,在这一章节中,我们重点介绍String()对象的属性和方法。
<script>
var str = "Hello World!";
console.log(str.constructor);
console.log(str.length);
</script>
说明:所有字符串方法都不会改变原始字符串
charAt()方法
语法:字符串.charAt(索引)
返回值:如果有该索引位置,就是索引位置的字符;如果没有该索引位置,则为空。
charCodeAt()方法
语法:字符串.charCodeAt(索引)
返回值:该索引位置的字符编码(UTF-8编码)
concat()方法
该方法可以用来连接两个或多个字符串
indexof()方法
该方法可以检索一个字符串中是否含有指定内容,如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有找到指定的内容,则返回-1,可以指定一个第二个参数,指定开始查找的位置
lastIndexOf()方法
该方法的用法和indexOf()一样,不同的是indexOf是从前往后找,而lastIndexOf是从后往前找,也可以指定开始查找的位置
<script>
var str = "Hello World!";
console.log(str.charAt(1)); //e
console.log(str.charCodeAt(1)); //101
console.log(str.concat("你好 ", "世界!")) //Hello World!你好 世界!
console.log(str.indexOf("o")); //4
console.log(str.indexOf("o", 5)); //7
console.log(str.lastIndexOf("o")); //7
console.log(str.lastIndexOf("o", 5)); //4
</script>
slice()方法
可以从字符串中截取指定的内容,不会影响原字符串,而是将截取到内容返回
参数:
第一个参数:开始位置的索引(包括开始位置)
第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的
注意:也可以传递一个负数作为参数,负数的话将会从后边计算。
<script>
var str = "Hello,World!";
var result = str.slice(1, 4);
console.log(result); //ell
result = str.slice(1);
console.log(result); //ello,World!
result = str.slice(1, -1);
console.log(result); //ello,World
</script>
substring()方法
可以用来截取一个字符串,它和slice()类似
参数:
第一个参数:开始截取位置的索引(包括开始位置)
第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的
注意:不同的是这个方法不能接受负值作为参数,如果传递了一个负值,则默认使用0,而且它还自动调整参数的位置,如果第二个参数小于第一个,则自动交换
<script>
var str = "Hello,World!";
var result = str.substring(1, 4);
console.log(result); //ell
var result = str.substring(4, 1);
console.log(result); //ell
result = str.substring(1);
console.log(result); //ello,World!
result = str.substring(2, -1);
console.log(result); //He
</script>
substr()方法
语法:字符串.substr(截取开始位置的索引,截取的长度)
作用:截取字符串
返回值:截取出来的字符串
split()方法
该方法可以将一个字符串拆分为一个数组,需要一个字符串作为参数,将会根据该字符串去拆分数组
<script>
var str = "Hello,World!";
var result1 = str.split(",");
var result2 = str.split("");
var result3 = str.split();
console.log(result1);
console.log(result2);
console.log(result3);
</script>
toUpperCase()方法
语法:字符串.toUpperCase()
作用:把字符串里的小写字母转成大写字母
返回值:转换好以后的字符串
toLowerCase()方法
语法:字符串.toLowerCase()
作用:把字符串里的大写字母转成小写字母
返回值:转换好以后的字符串
replace()方法
语法:字符串.replace(‘要被替换的字符’, ‘替换成的字符’)
作用:替换字符串内的某些字符。只能替换查找到的第一个。
返回值:替换好的字符
正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式,来检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来。
使用typeof检查正则对象,会返回object。
使用对象创建
语法格式:
var 变量名 = new RegExp("正则表达式","匹配模式");
匹配模式:
• i:忽略大小写
• g:全局匹配模式
• ig:忽略大小写且全局匹配模式
示例:
<script>
// 这个正则表达式可以来检查一个字符串中是否含有a
var reg = new RegExp("ab", "i");
var str = "Abc";
var result = reg.test(str);
console.log(result); //true
</script>
使用字面量创建
语法格式:
var 变量名 = /正则表达式/匹配模式;
匹配模式:
• i:忽略大小写
• g:全局匹配模式
• m:执行多行匹配
注意:可以为一个正则表达式设置多个匹配模式,且顺序无所谓
示例:
<script>
// 这个正则表达式可以来检查一个字符串中是否含有a
var reg = /a/i;
var str = "Abc";
var result = reg.test(str);
console.log(result); //true
</script>
使用 |
表示或者的意思
[ ]
里的内容也是或的关系
常见组合:
[a-z]:任意小写字母
[A-Z]:任意大写字母
[A-z]:任意字母
[0-9]:任意数字
[^字符序列]
表示除了某些字符序列
常见组合:
[^a-z]:除了任意小写字母
[^A-Z]:除了任意大写字母
[^A-z]:除了任意字母
[^0-9]:除了任意数字
这些正则方法其实都是字符串的方法,但是它的参数需要传递正则表达式,在这里,我就先称为正则方法。
split()方法
该方法可以将一个字符串拆分为一个数组,方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串,这个方法即使不指定全局匹配,也会全都拆分
<script>
var str = "1a2b3c4d5e6f7";
var result = str.split(/[A-z]/);
console.log(result);
</script>
search()方法
该方法可以搜索字符串中是否含有指定内容,如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1,它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串,serach()只会查找第一个,即使设置全局匹配也没用
<script>
var str = "hello abc hello aec afc";
var result = str.search(/a[bef]c/);
console.log(result); //6
</script>
match()方法
该方法可以根据正则表达式,从一个字符串中将符合条件的内容提取出来,默认情况下我们的match()只会找到第一个符合要求的内容,找到以后就停止检索,我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容,可以为一个正则表达式设置多个匹配模式,且顺序无所谓,match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
<script>
var str = "1a2a3a4a5e6f7A8B9C";
var result = str.match(/[a-z]/ig);
console.log(result);
</script>
replace()方法
该方法可以将字符串中指定内容替换为新的内容,默认只会替换第一个,但是可以设置全局匹配替换全部
参数:
第一个参数:被替换的内容,可以接受一个正则表达式作为参数
第二个参数:新的内容
<script>
var str = "1a2a3a4a5e6f7A8B9C";
var result = str.replace(/[a-z]/gi, "@_@");
console.log(result);
</script>
通过量词可以设置一个内容出现的次数,量词只对它前边的一个内容起作用,如果有多个内容可以使用 ()
括起来,常见量词如下:
{n}
:正好出现n次
{m,}
:出现m次及以上
{m,n}
:出现m-n次
+
:至少一个,相当于{1,}
*
:0个或多个,相当于{0,}
?
:0个或1个,相当于{0,1}
<script>
var str = "abbc";
reg = /(ab){3}/;
console.log(reg.test(str)); //false
reg = /b{3}/;
console.log(reg.test(str)); //false
reg = /ab{1,3}c/;
console.log(reg.test(str)); //true
reg = /ab{3,}c/;
console.log(reg.test(str)); //false
reg = /ab+c/;
console.log(reg.test(str)); //true
reg = /ab*c/;
console.log(reg.test(str)); //true
reg = /ab?c/;
console.log(reg.test(str)); //false
</script>
如果我们要检查或者说判断是否以某个字符或者字符序列开头或者结尾就会使用^
和$
。
^
:表示开头,注意它在[^字符序列]
表达的意思不一样
$
:表示结尾
<script>
var str = "abcabca";
// 检查一个字符串中是否以a开头
var reg1 = /^a/;
console.log(reg1.test(str)); //true
// 检查一个字符串中是否以a结尾
var str = "abcabca";
var reg2 = /a$/;
console.log(reg2.test(str)); //true
</script>
其他特殊字符:
/
:转义字符\w
:任意字母、数字、_,相当于[A-z0-9_]
\W
:除了字母、数字、_,相当于[^A-z0-9_]
\d
:任意的数字,相当于[0-9]
\D
:除了任意的数字,相当于[^0-9]
\s
:空格\S
:除了空格\b
:单词边界\B
:除了单词边界点击移步