JavaScript学习总结
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
变量
// 声明变量
var data;
// 多个变量
var age = 18,
year = 19999;
// 只声明不赋值
var age;
console.log(age); // undefined
// 不声明不赋值
console.log(xx); // Uncaught ReferenceError: xx iis not defined
// 不声明,直接赋值
page = 1;
console.log(page); // 可以正常输出1
如果在函数内部没有声明直接赋值的变量属于全局变量
// num1 num3都是全局变量
var num1 = 1;
function fn() {
var num2 = 2;
num3 = 3;
}
console.log(num1);
console.log(num2);
console.log(num3);
数据类型
js的变量数据类型只有在程序的运行过程中,根据赋值号右边的值来确定
// 类型可变
var x = 6;
x = '6';
// 简单数据类型
// Number String Boolean Undefined Null
// Number
var age = 21;
var PI = 3.1415926;
var bNum = 0b10; // 二进制
var oNum = 0123; // 八进制
var hNum = 0xABC; // 十进制
// Number型的最大值和最小值
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324
// 无空大
console.log(Infinity);
// 无穷小
console.log(-Infinity);
// Not a Number
console.log(NaN);
// "adfas" - 12; 这就是NaN
// 但 “123” - 12 和 '123' - 12不是,会计算出111
// 判断是否是非数字: isNaN()
// isNaN("123") 和 isNaN(123) 返回的都是false
// String
var s1 = "string_type_1";
var s2 = 'string_type_2'; // js推荐用单引号,因为HTML用双引号
// 字符串长度(不是函数)
s1.length;
// 字符串拼接
var s3 = "123" + 12; // 输出"12312"这一点与"123"-12非常不同需要注意
// Boolean
// true
// false
// Undefined
var ud1;
var ud2 = undefined;
console.log(ud1 + 'haha'); // 输出 undefinedhaha
console.log(ud2 + 1); // 输出NaN
// Null
var null1 = null;
console.log(null1 + "haha"); // 输出: nullhaha
console.log(null1 + 1); // 输出:1
// 复杂数据类型
// Object
检测数据类型: typeof
var num = 10;
console.log(typeof num); // number
var str = 'hello'
console.log(typeof str); // string
var bool = false;
console.log(typeof bool); // boolean
// 这里特别注意null是object类型
var null1 = null;
console.log(typeof null1); // object
数据类型转换
// 转换为字符串类型
// 方法1: toString()
var num1 = 10;
var str1 = num1.toString();
// 方法2: String()强制类型转换
var str2 = String(num1);
// 方法3: 加号拼接字符串,又称隐式转换
var str3 = num + '';
// 转换为数字型
// 方法1: parseInt() parseFloat()
var str1 = "123";
var num1 = parseInt(str1);
// parseInt会向下取整
parseInt("3.14"); // 3
parseInt("2.72"); // 2
// parseInt自动去掉尾部
parseInt("120px"); // 120
parseInt("F120px"); // NaN
// 方法2: Number强制类型转换
// 方法3: 利用 - * / > < >= <= 隐式转换
console.log('12' - 0);
console.log('12' - '10');
// 转换为Boolean
// 代表空、否定的值会被转换成false;其余的被转换为true
// 以下全为false
Boolean('');
Boolean(0);
Boolean(NaN);
Boolean(undefined);
Boolean(null);
// 以下全为true
Boolean(123);
Boolean('null');
比较运算符全等:===
!==
要求全部数据类型一致
switch-case
隐式用的是全等方式
console.log(37 == '37'); // true
console.log(37 === '37'); // false
分支-循环
略
数组
声明方法
// 数组有两种创建方式
// 方法1: 利用数组字面量创建
var arr1 = [1, 2, 3, 4, 5];
// 方法2: 利用 new创建数组
var arr2 = new Array();
// 数组内的类型不一定要一样
var arr3 = [1, "2"];
// 空数组
var arr4 = [];
// 访问不存在的下标返回undefined
添加元素
// 数组元素个数: 数组名.length
// length属性不仅可读,还可写
// 方法1
var arr1 = Array();
arr1.length = 3;
console.log(arr1); // [empty x 3], 每个元素都是undefined
// 方法2:
var arr2 = [1, 2];
arr2[4] = 5; // 追加
// [
// 1,
// 2,
// null,
// null,
// 5
// ]
判断是否为数组: if(arr instanceof Array){}
或Array.isArray(arr)
“
添加删除:
- 末尾添加一个或多个:
push(x1, x2...)
- 末尾删除一个元素:
pop
- 数组开头添加一个或多个:
unshift(x1, x2...)
- 删除数组第一个元素:
shift()
返回数组元素索引号: indexOf
,不存在则返回-1
var arr = ['red', 'green', 'blue', 'green'];
console.log(arr.indexOf('green')); // 只返回1
console.log(arr.lastIndexOf('green')); //只返回3
数组转字符串: toString()
、join('分隔符')
遍历数组
var arr = [1, 2, 3, 4, 6];
arr.forEach(function(value){
console.log(value);
});
// obj就是arr
arr.forEach(function(value, index, obj){
console.log(value, index, obj);
});
函数
函数有两种声明方式
// 方式1:
function fn() {
// ...
}
// 方式2: 匿名函数
var fn = function {
// ...
}
函数如果没有return
则返回的是一个undefined
。
利用arguments
实现不定参数
function fn() {
console.log(arguments);
}
fn(1, 2, 3);
// 返回
// {
// "0": 1,
// "1": 2,
// "2": 3
// }
arguments
是一个伪数组:
- 具有
length
属性 - 按索引方式存储数据
- 不具有数组的
push
,pop
等方法
对象 Object
创建对象的方法
1. 利用对象字面量
var emptyObj = {};
var objA = {
name: 'namexx',
age: 120,
sayHi: function() {
console.log('hi~');
}
}
// 使用方法
objA.name;
objA['age'];
2. 利用new Object
var emptyObj = new Object();
var objA = new Object();
objA.name = 'sdfasd';
objA.age = 119;
objA.sayHi = function() {
console.log("hi~~~");
}
3. 利用构造函数
上面的方法一次只能创建一个对象
构造函数是一种特殊的函数,主要用来初始化对象,它总与new运算符一起使用。可以把类中一些公共属性和方法抽象出来,封装到构造函数里。
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {
// ...
}
}
new 构造函数名();
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHi = function() {
// ...
}
// 构造函数不需要return
}
var p = new Person('asdf', 34);
console.log(typeof p); // object
遍历对象
for (var k in p) {
console.log(k); // 得到属性名
console.log(obj[k]); // 得到属性值
}
箭头函数
箭头函数总体来说是一种函数的省略形式
基本语法
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
//相当于:(param1, param2, …, paramN) =>{ return expression; }
// 当只有一个参数时,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
// 没有参数的函数应该写成一对圆括号。
() => { statements }
=>
相当于两个部分的综合
function
:=>
前的参数列表之前相当于存在一个function
关键字return
:=>
后的函数体相当于处于return
关键字之后
以下两个代码效果一样,相当于省略了关键字function
var inx = 0;
array.forEach(function () { console.log(inx++); });
var inx = 0;
array.forEach(() => { console.log(inx++); });
对于=>
含有return
功能体现如下:
var inx = 0;
array.forEach(function () {
var fn = () => inx++;
console.log(fn());
});
输出
0
1
2
3
如果只有一个参数,可以省略括号
var array = ["Apple", "Tencent", "Google", "Meta"];
array.forEach(element => {
console.log(element);
});
如果只有一个语句,可以省略花括号
var array = ["Apple", "Tencent", "Google", "Meta"];
array.forEach(element => console.log(element));
如果没有参数,或有多个参数,则括号不能省略
Promise
Promise
接收一个名为executor
的函数参数。
形式定义如:executor: (resolve: (value: any) => void, reject: (reason?: any) => void) => void
也就是说,executer
接收两个函数参数resolve
和reject
。
在使用Promise
时需要注意的是,**executer
是同步执行的,在executer
内可以启动一个异步任务。
var p = new Promise((resolve, reject) => {
console.log("enter promise");
setTimeout(() => {
console.log("timeout");
if (Math.random() < 0.5) {
resolve("< 0.5");
} else {
reject(">= 0.5");
}
}, 1000);
console.log("exit promise");
}).then(
value => console.log("value: ", value),
reason => console.log("reason: ", reason)
);
console.log("after promise");
以上代码的时序如下:
enter promise
exit promise
after promise
timeout
value: < 0.5 或 reason: >= 0.5
上述代码与如下等价
var p = new Promise((resolve, reject) => {
console.log("enter promise");
setTimeout(() => {
console.log("timeout");
if (Math.random() < 0.5) {
resolve("< 0.5");
} else {
reject(">= 0.5");
}
}, 1000);
console.log("exit promise");
})
.then(value => console.log("value: ", value))
.catch(reason => console.log("reason: ", reason)
);
console.log("after promise");
如果在executer
内部不启动异步任务的话:
var p = new Promise((resolve, reject) => {
console.log("enter promise");
if (Math.random() < 0.5) {
resolve("< 0.5");
} else {
reject(">= 0.5");
}
console.log("exit promise");
}).then(
value => console.log("value: ", value),
reason => console.log("reason: ", reason)
);
console.log("after promise");
时序如下
enter promise
exit promise
after promise
value: < 0.5 或 reason: >= 0.5
async/await
async
关键字能定义一个异步函数,该函数返回一个Promise
对象
function asyncFunction1() {
console.log("in asyncFunction1");
return new Promise(resolve => {
setTimeout(() => {
resolve("resolved");
}, 1000);
}).then(value => console.log("resolved: ", value));
}
async function asyncTest() {
console.log("enter asyncTest");
asyncFunction1();
console.log("exit asyncTest");
}
console.log("before call asyncTest");
asyncTest();
console.log("after call asyncTest");
输出如下:
before call asyncTest
enter asyncTest
in asyncFunction1
exit asyncTest
after call asyncTest
resolved: resolved
如果在调用asyncFunction1
前加一个await
关键字,则会一直等到asyncFunction1
的异步任务执行完成
function asyncFunction1() {
console.log("in asyncFunction1");
return new Promise(resolve => {
setTimeout(() => {
resolve("resolved");
}, 1000);
}).then(value => console.log("resolved: ", value));
}
async function asyncTest() {
console.log("enter asyncTest");
await asyncFunction1();
console.log("exit asyncTest");
}
console.log("before call asyncTest");
asyncTest();
console.log("after call asyncTest");
输出如下:
before call asyncTest
enter asyncTest
in asyncFunction1
after call asyncTest // 这意味着asyncTest是被异步执行的
resolved: resolved
exit asyncTest // 这意味着await是等到了asyncFunction1里的异步任务结束
捕获结果
resolve
的结果可以直接拿到,reject
的结果可以用try/catch
的方式捕获。
function asyncFunction1() {
console.log("in asyncFunction1");
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("timeout");
if (Math.random() < 0.5) {
resolve("< 0.5");
} else {
reject(">= 0.5");
}
}, 1000);
})
}
async function asyncTest() {
console.log("enter asyncTest");
try {
result = await asyncFunction1();
console.log("result: ", result);
} catch (e) {
console.log("exception: ", e);
}
console.log("exit asyncTest");
}
console.log("before call asyncTest");
asyncTest();
console.log("after call asyncTest");
有两种输出可能
可能一:
before call asyncTest
enter asyncTest
in asyncFunction1
after call asyncTest
timeout
result: < 0.5
exit asyncTest
可能二:
before call asyncTest
enter asyncTest
in asyncFunction1
after call asyncTest
timeout
exception: >= 0.5
exit asyncTest
async
定义的函数一般用来执行网络需要很长时间的操作?
await
的存在大概就是可以在异步函数(async function
)里可以按同步的方式等待异步调用返回结果。
事件对象
事件对象属性、方法 | 说明 |
---|---|
e.target | 触发事件的对象 |
e.type | 事件的类型,比如click、mouseover[不带on] |
e.preventDefault() | 该方法阻止默认事件,比如不让链接跳转 |
e.stopPropagation() | 该方法阻止事件流冒泡 |
其它
innerText
、innerHTML
element.innerText
: 从起始位置到终止位置的内容,但不识别html标签,同时空格和换行也会去掉element.innerHTML
: 从起始位置到终止位置的全部内容,会识别html标签,同时保留空格和换行
innerHTML是W3C标准,innerText不是。