JavaScript
基础
输出
alert("hello"); // 弹出警告对话框
document.write("hello"); // 向body中输出内容
console.log("hello"); // 向控制台输出
输入
prompt
函数可以弹出带文本框的提示框,输入的内容作为返回值(字符串类型),参数为提示文字。
result = prompt("请输入文字:");
编写位置
script标签中
type可以省略
<script type="text/javascript">
alert("hello");
</script>
导入外部js
如果script标签使用了src属性,则标签之间的js代码会被忽略。
<script src="script.js"></script>
一些标签的属性中
<button onclick="alert('hello');">按钮</button>
<a href="javascript:alert('hello');">超链接1</a>
<a href="javascript:;">超链接2</a>
基本语法
严格区分大小写
(强烈建议)以
;
结尾标识符:由字母、数字、
_
、$
组成,不能以数字开头字符串单双引号都可以
数据类型
6种数据类型:String、Number、Boolean、Null、Undefined、Object
检查变量类型
var a = 123;
console.log(typeof a);
Number
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
// 超过最大值的话
var a = Number.MAX_VALUE * Number.MAX_VALUE;
console.log(a); // Infinity,如果是负的话就是-Infinity
console.log(typeof Infinity); // number,Infinity是字面量
// NaN也是字面量
var b = "abc" * "bcd";
console.log(b); // NaN
console.log(typeof NaN); // number
进制
- 16进制:
0x
开头 - 8进制:
0
开头 - 2进制:
0b
开头,但不是所有的浏览器都支持
Boolean
true
和false
Null
null
:表示空对象
console.log(typeof null); // object
Undefined
undefined
:声明但未赋值的变量
console.log(typeof undefined); // undefined
强制类型转换
转为String
// 方法一
// Number Boolean可以使用toString()方法,null或undefined使用此方法会报错
var a = 123;
console.log(typeof a.toString());
// 方法二
// 用String()方法,支持null和undefined
console.log(typeof String(a));
转为Number
// 方法一
// Number()方法.不能转换则输出NaN,空串或空白字符串输出0;true转为1,false转为0;null转为0;undefined转为NaN
a = "123";
b = Number(a);
// 方法二
// parseInt()。从左往右提取整数,遇到其他字符则停止
// parseFloat()。同理提取小数
// 对于非String类型,会先转换为String,再parse
a = "123.456px";
b = parseInt(a); // 123
c = parseFloat(a); // 123.456
parseInt(true); // N
a = "070";
b = parseInt(a); // 有些浏览器会当成十进制,有些当成八进制
c = parseInt(a, 8); // 指定进制
转为Boolean
// Boolean()
// 数字:0, NaN是false
// 字符串:空串是false
// null, undefined是false
// 其余都是true
运算符
typeof
的结果类型为字符串算数运算符
+ - * / %
非数值参与运算先转为数值(除字符串加法)
任何值和
NaN
运算结果都为NaN
(除字符串加法)字符串相加为拼接
任何值和字符串相加都会将该值转换为字符串再拼接
一元运算符
+ -
- 对于非数值类型会先转换为数字,如
+"123"
的结果为数值123
- 对于非数值类型会先转换为数字,如
自增
++
, 自减--
逻辑运算符
! && ||
短路计算
非布尔值先转换为布尔值,返回的是原值
// 与运算:如果第一个值为true,返回第二个值;如果第一个值为false,返回第一个值 console.log(5 && 6); // 6 console.log(0 && 2); // 0 console.log(2 && 0); // 0 console.log(NaN && 0); // NaN console.log(0 && NaN); // 0 // 或运算:第一个为true,返回第一个;第一个为false,返回第二个 console.log(2 || 1); // 2 console.log(NaN || 1); // 1
赋值运算符
=
、+=
、-=
、...关系运算符
- 非数值转换为数值
- 任何值和NaN做任何比较都为false
- 如果两边都是字符串,会比较字符串中字符的unicode编码(一个一个比;如果前面的字符相同,有字符大于空字符,
"ab" > "a"
)
相等运算符
==
、!=
类型不同会转换为相同的类型
特殊情况
console.log(null == 0); // false console.log(null == undefined); // true // NaN不等于任何值包括它自己
通过
isNaN()
函数判断是否为NaN
===
、!==
- 类型不同直接返回
条件运算符(三元运算符):
条件 ? 语句1 : 语句2
使用Unicode
js中:
\u + 4位16进制编码
HTML中:
&#十进制编码;
代码块
{}
只有分组的作用。代码块内的内容在代码块外完全可见。
条件语句
if () {
} else if () {
} else {
}
switch () {
case 表达式:
语句
break;
case 表达式:
语句
break;
default:
语句
}
循环语句
while (条件) {
}
do {
} while (条件);
for (;;) {
}
break和continue
可以为循环创建一个标签,break或continue后加标签将会结束指定的循环而不是最近的。
// 输出1 1后结束
outer:
for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= 5; j++) {
console.log(i, j);
break outer;
}
}
// 输出1 1到5 1
outer:
for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= 5; j++) {
console.log(i, j);
continue outer;
}
}
对象
分类
- 内建对象:由ES标准定义的对象,在任何ES的实现中都可以使用。如:Math、String、Number、Boolean、Function、Object……
- 宿主对象:由JS运行环境提供的对象(主要指浏览器提供的对象)。如:BOM(浏览器对象)、DOM(文档对象)
- 自定义对象
基本操作
// 使用new关键字调用的函数是构造函数
var obj = new Object();
// 向对象添加属性
obj.name = "孙悟空";
obj.gender = "男";
// 读取属性
console.log(obj.name);
// 读取对象中没有的属性会返回undefined
console.log(obj.hello);
// 修改属性值
obj.name = "Tom";
// 删除属性
delete obj.name;
属性名和属性值
属性名不强制要求遵守标识符的规范。
如果要使用特殊的属性名,不能采用.
的方式操作,使用对象["属性名"]
的方式。
使用[]
的方式操作属性更灵活,[]
中可以传递一个变量。
obj["123"] = 789;
var tmp = "123";
console.log(obj["123"]);
console.log(obj[tmp]);
属性值可以是任意数据类型。
in
运算符可以检查一个对象中是否含有指定的属性。
console.log("name" in obj);
console.log("hello" in obj);
字面量
和调用构造方法一样,可以同时指定属性。
字面量的属性名可以加引号也可以不加(推荐),如果使用特殊的名字必须加引号。最后一个属性之后没有逗号。
var obj = {};
obj.name = "孙悟空";
var obj = {
name: "猪八戒",
age: 29,
test: {
name: "沙和尚"
}
};
函数
函数也是一个对象。
// 创建1:几乎不用
var fun = new Function();
console.log(typeof fun); // function
// 可以将代码以字符串的形式传给构造函数
var fun = new Function("console.log('hello')");
// 创建2:使用函数声明
function fun2(形参) {
}
// 创建3(将匿名函数赋值给变量)
var fun3 = function(形参) {
};
// 调用函数
fun(实参);
参数
调用函数时,不会检查实参的类型。
也不会检查实参的数量,多余的不会被赋值,少了的话形参就是undefined。
参数可以是任意类型,包括对象、函数。
function sum(a, b) {
console.log(a + b);
}
sum(123, 456, "hello"); // 579
返回值
return语句后不写任何值或不写return语句,则返回undefined。
返回值可以是任意类型,包括函数。
function sum(a, b) {
return a + b;
}
var result = sum(1, 2);
function fun() {
function fun2() {
alert("hello");
}
return fun2;
}
fun()();
立即执行函数
// 函数用()包起来表示一个整体,不然会报错
(function sum(a, b) {
console.log(a + b);
})(123, 456);
call和apply方法
fun()
、fun.call()
、fun.apply()
都可以调用函数- call和apply会将第一个参数指定为函数中的this
- call依次传实参,apply以数组的形式传参
function sum(a, b) {
console.log(this.name, a + b);
}
var obj = {name: "Tom"};
sum.call(obj, 1, 2);
sum.apply(obj, [1, 2]);
arguments
表示函数的参数。和this
一样,是传给函数的隐含参数。arguments
是一个类数组对象(不是Array),可以用索引操作和获取长度。它有一个属性callee
,就是当前的函数对象。不论有没有写形参,都能通过arguments
获取到传入的实参。
function fun(a) {
var b = arguments[1];
console.log(arguments.length); // 2
console.log(a, b); // 1 2
console.log(arguments.callee == fun); // true
}
fun(1, 2);
方法
函数作为一个对象的属性。
var obj = new Object();
obj.name = "孙悟空";
obj.sayName = function() {
}
var obj2 = {
name: "猪八戒",
sayName: function() {
}
}
枚举属性
// 将obj的属性名赋值给n
for (var n in obj) {
console.log(n, obj[n]); // 输出属性名和属性值
}
作用域
全局作用域
页面打开时创建,关闭时销毁。
全局作用域中有一个全局对象
window
,代表浏览器窗口,由浏览器创建可以直接使用。在全局作用域创建的变量都会作为
window
对象的属性保存。var a = 10; console.log(window.a);
在全局作用域创建的函数都会作为
window
对象的方法保存。
变量的声明提前
使用var
关键字声明的变量会在所有的代码执行之前被声明,如果声明变量不使用var
,则不会声明提前。
a = 10; // 相当于window.a
console.log(a); // 10
console.log(a); // 报错,a未定义
a = 10;
// 相当于在最前面声明了a,所以没有报错
console.log(a); // undefined
var a = 10;
// 等价于
var a;
console.log(a); // undefined
a = 10;
函数的声明提前
使用函数声明形式创建的函数会在所有代码执行之前被创建。
fun(); // 不会报错
function fun() {
console.log("hello");
}
fun2(); // 报错,未定义
var fun2 = function() {
console.log("hi");
}
函数作用域
调用时创建,函数执行完毕后销毁。
函数作用域中访问全局变量加window.
。
也有声明提前。
在函数中不使用var声明的变量都会成为全局变量。
var a = 1;
function fun() {
a = 2;
b = 3;
}
fun();
console.log(a, b); // 2 3
this
调用函数时会向函数传递一个隐含参数this,称为函数执行的上下文对象,根据函数调用方式的不同,this会指向不同的对象:
- 以函数形式调用,this是
window
- 以方法形式调用,this是调用方法的对象
其实第一种是第二种的特殊情况,直接调用函数相当于window.xxx
。
var name = "孙悟空";
function fun() {
console.log(this.name);
}
var obj = {
name: "沙和尚",
sayName: fun
};
fun(); // 孙悟空
obj.sayName(); // 沙和尚
构造函数
就是一个普通的函数,习惯首字母大写。调用时需要使用new
关键字。
执行流程:
- 创建一个新对象
- 将新对象设置为函数中的this
- 执行函数代码
- 返回新对象
同一个构造函数创建的对象称为一类对象,也将构造函数称为一个类。将通过构造函数创建的对象称为该类的实例。
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
var person = new Person("孙悟空", 18, "男");
instanceof
检查一个对象是否是一个类的实例。所有对象都是Object的后代。
console.log(person instanceof Person);
原型(prototype)
每一个函数都有prototype
属性,这个属性对应一个对象,即原型对象。
当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性指向原型对象,可以通过__proto__
来访问。
原型对象相当于一个公共区域,同一个类的实例都可以访问,可以将对象中共有的内容设置到原型对象中。
当访问一个对象的属性或方法时:
- 先在对象自身寻找
- 没有则去原型对象中寻找
- 没有则去原型的原型中寻找
- 直到找到Object对象的原型。Object对象的原型没有原型。在Object的原型中依然没有找到则返回undefined
function MyClass() {
}
MyClass.prototype.a = 123;
MyClass.prototype.sayHello = function() {
console.log("hello");
}
var mc1 = new MyClass();
var mc2 = new MyClass();
console.log(mc1.__proto__ == mc2.__proto__); // true
console.log(mc1.a);
mc2.sayHello();
// 使用in关键字检查对象中是否含有某个属性时,如果原型中有也会返回true。
console.log("a" in mc1); // true
// 使用对象的hasOwnProperty()来检查自身对象中是否含有该属性
console.log(mc1.hasOwnProperty("a")) // false
// 原型链
console.log(mc1.__proto__.__proto__); // Object
console.log(mc1.__proto__.__proto__.__proto__); // null
结论:创建构造函数时可以将共有的属性和方法添加到原型对象中。
toString
打印一个对象相当于输出对象toString方法的返回值。toString方法定义在Object的原型中。
console.log(mc1.__proto__.__proto__.hasOwnProperty("toString")); // true
// 为Person原型添加toString方法覆盖Object原型的toString方法
Person.prototype.toString = function() {
return xxx;
};
垃圾回收(GC)
JS拥有垃圾自动回收机制,只需要我们将不再使用的对象设置为null。
数组
也是对象。使用数字(从0开始)作为索引操作元素。元素可以是任意类型。
基本操作
// 创建
var arr = new Array();
var arr = new Array(10); // 创建长度为10的数组
var arr = new Array(10, 20, 30); // 创建元素为10 20 30的数组
// 添加
arr[0] = 10;
arr[1] = 45;
arr[arr.length] = 62; // 向数组最后添加
// 读取
// 读取不存在的索引返回undefined
console.log(arr[0]);
// 获取长度
// 对于连续数组就是元素的个数,对于非连续数组结果为最大索引+1
console.log(arr.length);
// 修改长度
// 大于原长度,多余的会空出来
// 小于则多出的被删除
arr.length = 10;
字面量
使用[]
,还可以指定初始元素。
var arr = [];
var arr = ["hello", 1, true, null, undefined];
方法
push
向数组末尾添加一个或多个元素,并返回新的长度。
arr.push(1, 2, "唐僧");
var result = arr.push(1, 2, "唐僧");
pop
删除并返回数组最后一个元素。
arr.pop();
var result = arr.pop();
unshift
向数组开头添加一个或多个元素,并返回新数组的长度。
shift
删除并返回数组的第一个元素。
slice
提取指定开始到结尾位置(前闭后开)的元素,不会改变原数组。不传第二个参数表示取到尾。负数表示倒着数。
var arr = [0, 1, 2, 3, 4];
result = arr.slice(1, 3); // 1, 2
result = arr.slice(2); // 2, 3, 4
result = arr.slice(2, -1); // 2, 3
splice
删除数组中指定位置的元素,插入新元素,并返回被删除的元素。
- 参数1:开始位置索引
- 参数2:删除的数量(为0表示不删)
- 参数3及以后:插入到开始位置前面的元素
var arr = [0, 1, 2, 3, 4];
console.log(arr.splice(1, 2)); // 1, 2
console.log(arr); // 0, 3, 4
var arr = [0, 1, 2, 3, 4];
console.log(arr.splice(1, 2, 10, 11)); // 1, 2
console.log(arr); // 0, 10, 11, 3, 4
concat
连接两个或多个数组/元素,并返回新数组,不会改变原数组。
var result = arr.concat(arr2, arr3, "a", 1);
join
将数组转为字符串并返回,不改变原数组。可以指定分隔符(默认,
)。
var arr = [0, 1, 2, 3, 4];
console.log(arr.join("@")); // 0@1@2@3@4
reverse
反转数组,会修改原数组。
sort
排序,会修改原数组。对字符串或数字会按照unicode编码排序(所以用于数字排序可能会出错)。
var arr = [3, 11, 2];
arr.sort();
console.log(arr); // 11, 2, 3
可以指定比较函数,函数返回值大于0表示要交换。
arr.sort(function(x, y) {
return x - y; // 升序
return y - x; // 降序
});
遍历
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// 支持IE8以上浏览器
/* 浏览器会向函数传递三个参数
* 第一个参数:遍历的元素
* 第二个参数:元素的索引
* 第三个参数:遍历的数组
*/
arr.forEach(function(value, index, array) {
console.log(index, value, array);
});
Date
// 默认为当前时间
var d = new Date();
// 指定时间:月/日/年 时:分:秒
var d2 = new Date("01/10/2023 15:04:36");
// 方法
// 获取日
console.log(d2.getDate()); // 10
// 获取星期,0表示星期天
console.log(d2.getDay()); // 2
// 获取月,0~11
console.log(d2.getMonth()); // 0
// 获取年
console.log(d2.getFullYear()); // 2023
// 获取时间戳,1970.1.1
console.log(d2.getTime()); // 1673334276000
// 获取当前时间戳
console.log(Date.now());
Math
不是构造函数,是一个工具类。
属性:E
、PI
等
方法:abs()
、ceil()
、floor()
、round()
、random()
0到1的随机数、max()
、min()
、pow()
、sqrt()
等
包装类
String
、Number
、Boolean
var num = new Number(3);
当对一些基本数据类型的值去调用属性和方法时,浏览器会临时将其转换为包装类对象,然后再调用属性和方法,调用完再转换回基本数据类型。
String
在底层以数组形式保存。
var str = "hello";
console.log(str[0]); // h
console.log(str.length); // 5
方法
// 指定位置字符
console.log(str.charAt(0)); // h
// 指定位置字符的unicode编码
console.log(str.charCodeAt(0)); // 104
// 根据unicode编码获取字符
console.log(String.fromCharCode(104)); // h
// 拼接,同+
console.log(str.concat(" world")); // hello world
// 查找,第二个参数表示开始查找的位置。返回第一次出现的位置,否则-1
console.log(str.indexOf("h")); // 0
console.log(str.indexOf("h", 1)); // -1
console.log(str.lastIndexOf("l")); // 3
console.log(str.lastIndexOf("l", 2)); // 2
// 截取
str.slice // 同数组
str.substring // 不能传负数,负数会转为0,如果第二个参数小于第一个会交换参数
str.substr // 同substring,非标准方法
// 大小写转换
str.toLowerCase()
str.toUpperCase()
支持正则的方法
// 拆分。传空串则拆分每一个字符
console.log(str.split("e")); // ['h', 'llo']
console.log(str.split(/[a-z]/)); // 根据小写字母拆分
// 搜索。参数为普通字符同indexOf,参数还可以是正则表达式对象,返回第一次匹配的位置
console.log("skd6ds".search(/[0-9]/)); // 3
// 匹配。加g则匹配多个,返回数组。
console.log("1a2b3C".match(/[a-z]/)); // {'a', index: 1, input: '1a2b3C', groups: undefined}
console.log("1a2b3C".match(/[a-z]/g)); // ['a', 'b']
console.log("1a2b3C".match(/[a-z]/ig)); // ['a', 'b', 'C']
// 替换。加g替换多个
console.log("1a2a3A".replace(/[a-z]/ig, "@")); // 1@2@3@
正则表达式
// 创建正则表达式对象
// 构造函数:RegExp(正则表达式, 匹配模式)
// 字面量:/正则表达式/匹配模式
// 第二个参数是匹配模式:i 忽略大小写,g 全局匹配模式
var reg = new RegExp("a");
var reg2 = new RegExp("a", "i");
var reg3 = /a/i;
var reg4 = new RegExp("\\."); // 在构造函数中使用转义要两个\
// 检查匹配
console.log(reg.test("A")); // false
console.log(reg2.test("A")); // true
// 语法
| // 或
[ab],[a-z] // []中任意字符
[^0-9] // 除了
{n} // n次
{m,n} // m到n次
{m,} // m次以上
() // 括号
+ // 至少一次
* // 0次或多次
? // 0次或1次
^ // 开头
$ // 结尾
. // 任意字符
\ // 转义
\w // 任意字母、数字、下划线
\W // 与\w相反
\d // 任意数字
\D // 非数字
\s // 空白字符
\S // 非空白字符
\b // 单词边界
\B // 除了单词边界
// \b演示
console.log(/child/.test("hello children")); // true
console.log(/\bchild\b/.test("hello children")); // false
// 去除开头结尾空格
str.replace(/^\s*|\s*$/g, );