JavaScript
下表列出了 JavaScript 语句标识符 (关键字) :
语句 | 描述 |
---|---|
break | 用于跳出循环。 |
catch | 语句块,在 try 语句块执行出错时执行 catch 语句块。 |
continue | 跳过循环中的一个迭代。 |
do … while | 执行一个语句块,在条件语句为 true 时继续执行该语句块。 |
for | 在条件语句为 true 时,可以将代码块执行指定的次数。 |
for … in | 用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。 |
function | 定义一个函数 |
if … else | 用于基于不同的条件来执行不同的动作。 |
return | 退出函数 |
switch | 用于基于不同的条件来执行不同的动作。 |
throw | 抛出(生成)错误 。 |
try | 实现错误处理,与 catch 一同使用。 |
var | 声明一个变量。 |
while | 当条件语句为 true 时,执行语句块。 |
显示数据
window.alert()
window.alert(5 + 6);
操作 HTML 元素,innerHTML 获取or插入内容
document.getElementById("demo").innerHTML = '修改';
同时innerHTML也能获取到内容
document.write是直接写入到页面的内容流,如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖。
innerHTML则是DOM页面元素的一个属性,代表该元素的html内容。你可以精确到某一个具体的元素来进行更改。如果想修改document的内容,则需要修改document.documentElement.innerElement。
innerHTML将内容写入某个DOM节点,不会导致页面全部重绘。
innerHTML很多情况下都优于document.write,其原因在于其允许更精确的控制要刷新页面的哪一个部分
document.write()
<h1>我的第一个 Web 页面</h1> <p>我的第一个段落。</p> <button onclick="myFunction()">点我</button> <script> function myFunction() { document.write(Date()); } </script>
如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖
console.log()写到控制台
console.log("你好啊")
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol,Nan(不是数字)。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
**注:**Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
声明字符串
var carname=new String;
声明数字
var x= new Number;
声明数组
const a = new Array();
or
const b = [];
对象声明:
const a = new Object();
or
const b = {};
Undefined 和 Null
Undefined 这个值表示变量不含有值。
可以通过将变量的值设置为 null 来清空变量。
实例
cars=null;
person=null;
请不要把字符串,数字,bool创建为对象。它会拖慢执行速度。
new 关键字使代码复杂化。也可能产生一些意想不到的结果:
当使用 == 相等运算符时,相等字符串是相等的:
对象
对象定义
var person = {
firstName: "John",
lastName : "Doe",
id : 5566,
fullName : function()
{
return this.firstName + " " + this.lastName;
}
};
访问对象属性
person.lastName;
person["lastName"];
对象方法
执行函数
name = person.fullName();
输出函数字符串
name = person.fullName;
字符串
JavaScript 字符串用于存储和操作文本。
JavaScript 字符串是引号中的零个或多个字符。
您能够使用单引号或双引号:
实例
var carname = "Porsche 911"; var carname = 'Porsche 911';
可以在字符串中使用引号,只要不匹配围绕字符串的引号即可:
var answer = "It's good to see you again!"; var answer = "He is called 'Bill'"; var answer = 'He is called "Bill"';
\r 回车 \t 水平制表符
模板字符串(${}
)
使用这个方法规定字符串需要用 ` ` 包裹起来,
var a = '你好啊'; console.log(`一定要用这个符号包裹,下面是字符串内容:${a},这就成功了`); //一定要用这个符号包裹,下面是字符串内容:你好啊,这就成功了
字符串方法
字符串长度
length 属性返回字符串的长度:
var txt = "1234567"; var sln = txt.length; console.log(sln); //7
查找字符串中的字符串
indexOf()
方法返回字符串中指定文本首次出现的索引(位置):var str = " of China Republic of China."; var pos = str.indexOf("China"); //4
lastIndexOf()
方法返回指定文本在字符串中最后一次出现的索引:var str = " of China Republic of China."; var pos = str.lastIndexOf("China"); //23
如果未找到文本,
indexOf()
和lastIndexOf()
均返回 -1。两种方法都接受作为检索起始位置的第二个参数。
var str = " of China Republic of China."; var pos = str.indexOf("China",18); //23
检索字符串中的字符串
search() 方法搜索特定值的字符串,并返回匹配的位置:
var str = " of China Republic of China."; var pos = str.search("China"); //4
两种方法,indexOf() 与 search(),结果是相等的。
这两种方法是不相等的。区别在于:
- search() 方法无法设置第二个开始位置参数。
- indexOf() 方法无法设置更强大的搜索值(正则表达式)。
提取部分字符串
slice() 方法
slice() 提取字符串的某个部分并在新字符串中返回被提取的部分。
该方法设置两个参数:起始索引(开始位置),终止索引(结束位置)。
这个例子裁剪字符串中位置 7 到位置 13 的片段:
var str = "Apple, Banana, Mango"; var res = str.slice(7,13);
res 的结果是:
Banana
如果某个参数为负,则从字符串的结尾开始计数。
这个例子裁剪字符串中位置 -12 到位置 -6 的片段:
var str = "Apple, Banana, Mango"; var res = str.slice(-13,-7);
res 的结果是:
Banana
负值位置不适用 Internet Explorer 8 及其更早版本。
如果忽略第二个参数,则该方法将裁剪字符串的剩余部分:
var res = str.slice(7);
res 的结果是:
Banana, Mango
substring() 方法
substring() 类似于 slice()。
不同之处在于 substring() 无法接受负的索引。
var str = "Apple, Banana, Mango"; var res = str.substring(7,13);
res 的结果是:
Banana
如果省略第二个参数,则该 substring() 将裁剪字符串的剩余部分。
substr() 方法
substr() 类似于 slice()。
不同之处在于第二个参数规定被提取部分的长度。
var str = "Apple, Banana, Mango"; var res = str.substr(7,6);
res 的结果是:
Banana
如果省略第二个参数,则该 substr() 将裁剪字符串的剩余部分。
var str = "Apple, Banana, Mango"; var res = str.substr(7);
res 的结果是:
Banana, Mango
如果首个参数为负,则从字符串的结尾计算位置。
var str = "Apple, Banana, Mango"; var res = str.substr(-5);
res 的结果是:
Mango
第二个参数不能为负,因为它定义的是长度。
替换字符串内容
replace() 方法用另一个值替换在字符串中指定的值:
var str = "Please visit Microsoft!"; var n = str.replace("Microsoft", "W3School"); //Please visit W3School!
replace() 方法不会改变调用它的字符串。它返回的是新字符串。
默认地,replace() 只替换首个匹配:
var str = "Please visit Microsoft and Microsoft!"; var n = str.replace("Microsoft", "W3School"); //Please visit W3School and Microsoft!
默认地,replace() 对大小写敏感。因此不对匹配 MICROSOFT:
var str = "Please visit Microsoft!"; var n = str.replace("MICROSOFT", "W3School"); //此例无效,因为 MICROSOFT 为大写。
如需执行大小写不敏感的替换,请使用正则表达式 /i(大小写不敏感):
var str = "Please visit Microsoft!"; var n = str.replace(/MICROSOFT/i, "W3School"); //Please visit W3School!
请注意正则表达式不带引号。
如需替换所有匹配,请使用正则表达式的 g 标志(用于全局搜索):
var str = "Please visit Microsoft and Microsoft!"; var n = str.replace(/Microsoft/g, "W3School"); //Please visit W3School and W3School!
转换为大写和小写
通过 toUpperCase() 把字符串转换为大写:
var text1 = "Hello World!"; // 字符串 var text2 = text1.toUpperCase(); // text2 是被转换为大写的 text1
通过 toLowerCase() 把字符串转换为小写:
var text1 = "Hello World!"; // 字符串 var text2 = text1.toLowerCase(); // text2 是被转换为小写的 text1
concat() 连接多个字符串方法
concat() 连接两个或多个字符串:
var text1 = "Hello"; var text2 = "World"; text3 = text1.concat(" ",text2); //Hello World!
concat() 方法可用于代替加运算符。下面两行是等效的:
var text = "Hello" + " " + "World!"; var text = "Hello".concat(" ","World!"); //Hello World!
所有字符串方法都会返回新字符串。它们不会修改原始字符串。
正式地说:字符串是不可变的:字符串不能更改,只能替换。
String.trim()方法删除字符串两端的空白符
trim() 方法删除字符串两端的空白符:
var str = " Hello World! "; //Hello World!
把字符串转换为数组
可以通过 split() 将字符串转换为数组:
var txt = "a,b,c,d,e"; // 字符串 txt.split(","); // 用逗号分隔 //[a,b,c,d,e] var txt = "a b c d e"; // 字符串 txt.split(" "); // 用空格分隔 //[a,b,c,d,e] var txt = "a b c d e"; // 字符串 txt.split("|"); // 用竖线分隔 //[a,b,c,d,e]
如果省略分隔符,被返回的数组将包含 index [0] 中的整个字符串。
如果分隔符是 “”,被返回的数组将是间隔单个字符的数组:
var txt = "Hello"; // 字符串 txt.split(""); // 分隔为字符 //[h,e,l,l,o]
数字
Number 方法和属性
原始值(比如 3.14 或 2016),无法拥有属性和方法(因为它们不是对象)。
但是通过 JavaScript,方法和属性也可用于原始值,因为 JavaScript 在执行方法和属性时将原始值视作对象。
toString() 方法
toString() 以字符串返回数值。
所有数字方法可用于任意类型的数字(字面量、变量或表达式):
var x = 123; x.toString(); // 从变量 x 返回 123 (123).toString(); // 从文本 123 返回 123 (100 + 23).toString(); // 从表达式 100 + 23 返回 123
toExponential() 方法
toExponential() 返回字符串值,它包含已被四舍五入并使用指数计数法的数字。
参数定义小数点后的字符数:
var x = 9.656; x.toExponential(2); // 返回 9.66e+0 x.toExponential(4); // 返回 9.6560e+0 x.toExponential(6); // 返回 9.656000e+0
该参数是可选的。如果您没有设置它,JavaScript 不会对数字进行舍入。
toFixed()方法
会四舍五入
返回字符串值,它包含了指定位数小数的数字:
var x = 9.656; x.toFixed(0); // 返回 10 x.toFixed(2); // 返回 9.66 x.toFixed(4); // 返回 9.6560 x.toFixed(6); // 返回 9.656000
toFixed(2) 非常适合处理金钱。
toPrecision() 方法
会四舍五入
toPrecision() 返回字符串值,它包含了指定长度的数字:
var x = 9.656; x.toPrecision(); // 返回 9.656 x.toPrecision(2); // 返回 9.7 x.toPrecision(4); // 返回 9.656 x.toPrecision(6); // 返回 9.65600
把变量转换为数值
这三种 JavaScript 方法可用于将变量转换为数字:
方法 描述 Number() 返回数字,由其参数转换而来。 parseFloat() 解析其参数并返回浮点数。 parseInt() 解析其参数并返回整数。 这些方法并非数字方法,而是全局 JavaScript 方法。
Number() 方法
Number() 可用于把 JavaScript 变量转换为数值:
x = true; Number(x); // 返回 1 x = false; Number(x); // 返回 0 x = new Date(); Number(x); // 返回 1404568027739 x = "10" Number(x); // 返回 10 x = "10 20" Number(x); // 返回 NaN
如果无法转换数字,则返回 NaN。
Number() 还可以把日期转换为数字:
Number(new Date("2019-04-15")); // 返回 1506729600000 //上面的 Number() 方法返回 1970 年 1 月 1 日至今的毫秒数。
parseInt() 方法
parseInt() 解析一段字符串并返回数值。允许空格。只返回首个数字:
parseInt("10"); // 返回 10 parseInt("10.33"); // 返回 10 parseInt("10 20 30"); // 返回 10 parseInt("10 years"); // 返回 10 parseInt("years 10"); // 返回 NaN
如果无法转换为数值,则返回 NaN (Not a Number)。
可以用来取整(向下取整)
parseFloat() 方法
parseFloat() 解析一段字符串并返回数值。允许空格。只返回首个数字:
parseFloat("10"); // 返回 10 parseFloat("10.33"); // 返回 10.33 parseFloat("10 20 30"); // 返回 10 parseFloat("10 years"); // 返回 10 parseFloat("years 10"); // 返回 NaN
如无法转换为数值,则返回 NaN (Not a Number)。
数组
JavaScript 数组用于在单一变量中存储多个值。
var cars = ["Saab", "Volvo", "BMW"];
把数组转换为字符串
JavaScript 方法 toString() 把数组转换为数组值(逗号分隔)的字符串。
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.toString();
Banana,Orange,Apple,Mango
join() 方法也可将所有数组元素结合为一个字符串。
它的行为类似 toString(),但是您还可以规定分隔符:
var fruits = ["Banana", "Orange","Apple", "Mango"]; fruits.join(" * ");
Banana * Orange * Apple * Mango
pop()
pop() 方法从数组中删除最后一个元素:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; var x = fruits.pop(); // x 的值是 "Mango"
pop() 方法返回“被弹出”的值:
注:
//length 属性提供了向数组追加新元素的简易方法:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[fruits.length] = "Kiwi";
// 向 fruits 追加 "Kiwi"
push()
push() 方法(在数组结尾处)向数组添加一个新的元素:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; var x = fruits.push("Kiwi"); // x 的值是 5
push() 方法返回新数组的长度
shift() ‘‘位移元素’’
shift位移与弹出等同,但处理首个元素而不是最后一个。
方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引。
shift() 方法返回被“位移出”的字符串:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.shift(); // 返回 "Banana"
unshift() ‘‘位移元素’’
unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素:
unshift() 方法返回新数组的长度。
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.unshift("Lemon"); // 返回 5
更改元素
通过使用它们的索引号来访问数组元素:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits[0] = "Kiwi"; // 把 fruits 的第一个元素改为 "Kiwi"
删除元素
既然 JavaScript 数组属于对象,其中的元素就可以使用 JavaScript delete 运算符来删除:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; delete fruits[0]; // 把 fruits 中的首个元素改为 undefined //fruits[0] === undefined
注意:使用 delete 会在数组留下未定义的空洞。请使用 pop() 或 shift() 取而代之。
拼接数组
splice() 方法可用于向数组添加新项:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "Kiwi");
第一个参数(2)定义了应添加新元素的位置(拼接)。
第二个参数(0)定义应删除多少元素。
其余参数(“Lemon”,“Kiwi”)定义要添加的新元素。
splice() 方法返回一个包含已删除项的数组:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 2, "Lemon", "Kiwi"); //Apple,Mango
使用 splice() 来删除元素
通过聪明的参数设定,您能够使用 splice() 在数组中不留“空洞”的情况下移除元素:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(0, 1); // 删除 fruits 中的第一个元素
第一个参数(0)定义新元素应该被添加(接入)的位置。
第二个参数(1)定义应该删除多个元素。
其余参数被省略。没有新元素将被添加。
slice() 裁剪数组
slice() 方法用数组的某个片段切出新数组。
slice() 方法创建新数组。它不会从源数组中删除任何元素。
本例从数组元素 3 (“Apple”)开始切出一段数组:
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var citrus = fruits.slice(3); //Apple,Mango
slice() 可接受两个参数,比如 (1, 3)。
该方法会从 1 开始参数选取元素,直到结束参数3(不包括3)为止。
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var citrus = fruits.slice(1, 3); //Orange,Lemon
reverse()数组反转
reverse() 方法反转数组中的元素。
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.reverse(); // 反转元素顺序 //Mango,Apple,Orange,Banana
数组排序 sort()
sort() 方法以字母顺序对数组进行排序:
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.sort(); // 对 fruits 中的元素进行排序 //Apple,Banana,Mango,Orange
默认地,sort() 函数按照字符串顺序对值进行排序。
不过,如果数字按照字符串来排序,则 “25” 大于 “100”,因为 “2” 大于 “1”。
正因如此,sort() 方法在对数值排序时会产生不正确的结果。
我们通过一个比值函数来修正此问题:
数组升序
var points = [40, 100, 1, 5, 25, 10]; points.sort(function(a, b){ return a - b; }); //1,5,10,25,40,100
使用相同的技巧对数组进行降序排序:
var points = [40, 100, 1, 5, 25, 10]; points.sort(function(a, b){ return b - a; }); //100,40,25,10,5,1
排序对象数组
var cars = [ {type:"Volvo", year:2016}, {type:"Saab", year:2001}, {type:"BMW", year:2010}];
//升序排序 cars.sort(function(a, b){return a.year - b.year});
寻找数组最大值Math.max()
您可以使用
Math.max.apply
来查找数组中的最高值:function myArrayMax(arr) { return Math.max.apply(null, arr); }
Math.max.apply([1, 2, 3]) 等于 Math.max(1, 2, 3)。
//自制方法,更快 function myArrayMax(arr) { var len = arr.length var max = -Infinity; while (len--) { if (arr[len] > max) { max = arr[len]; } } return max; }
寻找数组最大值Math.max()
您可以使用 Math.min.apply 来查找数组中的最低值:
function myArrayMin(arr) { return Math.min.apply(null, arr); }
Math.min.apply([1, 2, 3]) 等于 Math.min(1, 2, 3)。
//自制方法,更快 function myArrayMin(arr) { var len = arr.length var min = Infinity; while (len--) { if (arr[len] < min) { min = arr[len]; } } return min; }
数组迭代方法
Array.forEach()
forEach() 方法为每个数组元素调用一次函数(回调函数)
无返回值
var txt = ""; var numbers = [45, 4, 9, 16, 25]; numbers.forEach(myFunction); function myFunction(value, index, array) { txt = txt + value + "<br>"; }
**注释:**该函数接受 3 个参数:
- 项目值
- 项目索引
- 数组本身
forEach() 本身是不支持的 continue 与 break 语句的
continue 实现
var arr = [1, 2, 3, 4, 5]; arr.forEach(function (item) { if (item === 3) { return; } console.log(item); });
break 实现
抛出异常的形式结束
var arr = [1, 2, 3, 4, 5]; try { arr.foreach(**function** (item) { if(item===3) throw Error(); console.log(item); }); }catch(e){}
Array.map()
map() 方法通过对每个数组元素执行函数来创建新数组。
map() 方法不会对没有值的数组元素执行函数。
map() 方法不会更改原始数组。
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
请注意,该函数有 3 个参数:
- 项目值
- 项目索引
- 数组本身
这个例子将每个数组值乘以2:
var numbers1 = [45, 4, 9, 16, 25]; var numbers2 = numbers1.map(function(value, index, array){ return value * 2; });
Array.filter()
filter() 方法创建一个包含通过测试的数组元素的新数组。
这个例子用值大于 18 的元素创建一个新数组:
请注意此函数接受 3 个参数:
- 项目值
- 项目索引
- 数组本身
var numbers = [45, 4, 9, 16, 25]; var over18 = numbers.filter(myFunction); function myFunction(value, index, array) { return value > 18; //为true则加入新数组,false则不加 }
Array.reduce()
reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。
reduce() 方法在数组中从左到右工作。
reduce() 方法不会减少原始数组。
请注意此函数接受 4 个参数:
- 总数(初始值/先前返回的值) (第一次运行时的值为数组的第一项的值)
- 项目值
- 项目索引
- 数组本身
这个例子确定数组中所有数字的总和:
var numbers1 = [45, 4, 9, 16, 25]; var sum = numbers1.reduce(myFunction); function myFunction(total, value, index, array) { return total + value; }
Array.every()
every() 方法检查所有数组值是否通过测试。
这个例子检查所有数组值是否大于 18:
var numbers = [45, 4, 9, 16, 25]; var allOver18 = numbers.every(function(value, index, array){ return value > 18; }); //false 要求全部大于18以后,才能领其值为true
Array.some()
some() 方法检查某些数组值是否通过了测试。
这个例子检查某些数组值是否大于 18:
var numbers = [45, 4, 9, 16, 17]; var someOver18 = numbers.some(function(value, index, array) { return value > 18; }); //true,只要有一个是true,就是true
请注意此函数接受 3 个参数:
- 项目值
- 项目索引
- 数组本身
Array.indexOf()
indexOf() 方法在数组中搜索元素值并返回其位置。
**注释:**第一个项目的位置是 0,第二个项目的位置是 1,以此类推。
检索数组中的项目 “Apple”:
var fruits = ["Apple", "Orange", "Apple", "Mango"]; var a = fruits.indexOf("Apple"); //0
语法
array.indexOf(item, start)
item 必需。要检索的项目。 start 可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到结尾。 如果未找到项目,Array.indexOf() 返回 -1。
如果项目多次出现,则返回第一次出现的位置。
Array.lastIndexOf()
Array.lastIndexOf() 与 Array.indexOf() 类似,但是从数组结尾开始搜索。
Array.find()
find() 方法返回通过测试函数的第一个数组元素的值。
这个例子查找(返回)大于 18 的第一个元素的值:
var numbers = [4, 9, 16, 25, 29]; var first = numbers.find(function(value, index, array) { return value > 18; }); //25
请注意此函数接受 3 个参数:
- 项目值
- 项目索引
- 数组本身
Array.findIndex()
findIndex() 方法返回通过测试函数的第一个数组元素的索引。
这个例子查找大于 18 的第一个元素的索引:
var numbers = [4, 9, 16, 25, 29]; var first = numbers.findIndex(function(value, index, array) { return value > 18; });
请注意此函数接受 3 个参数:
- 项目值
- 项目索引
- 数组本身
日期
var d = new Date();
//默认情况下,JavaScript 将使用浏览器的时区并将日期显示为全文本字符串:
//Wed Dec 30 2020 16:20:44 GMT+0800 (中国标准时间)
创建 Date 对象
Date 对象由新的 Date() 构造函数创建。
有 4 种方法创建新的日期对象:
- new Date()
- new Date(year, month, day, hours, minutes, seconds, milliseconds)
- new Date(milliseconds)
- new Date(date string)
new Date()
new Date() 用当前日期和时间创建新的日期对象:
/日期对象是静态的。计算机时间正在滴答作响,但日期对象不会。
var d = new Date(); ////Wed Dec 30 2020 16:20:44 GMT+0800 (中国标准时间)
new Date(year, month, …)
new Date(year, month, …) 用指定日期和时间创建新的日期对象。
7个数字分别指定年、月、日、小时、分钟、秒和毫秒(按此顺序):
var d = new Date(2018, 11, 24, 10, 33, 30, 0); //Sat Jan 25 2020 10:33:30 GMT+0800 (中国标准时间) //6个数字指定年、月、日、小时、分钟、秒: //5个数字指定年、月、日、小时和分钟: //4个数字指定年、月、日和小时: //3 个数字指定年、月和日: //2个数字指定年份和月份: //您不能省略月份。如果只提供一个参数,则将其视为毫秒。
注释:JavaScript 从 0 到 11 计算月份。一月是 0。十二月是11。
new Date(dateString)
new Date(dateString) 从日期字符串创建一个新的日期对象:
var d = new Date("October 13, 2014 11:13:00"); //Wed Dec 25 2019 12:46:00 GMT+0800 (中国标准时间)
格式转换
toUTCString()
toUTCString() 方法将日期转换为 UTC 字符串(一种日期显示标准)。
var d = new Date().toUTCString(); //Wed, 30 Dec 2020 08:58:18 GMT
toDateString()
toDateString() 方法将日期转换为更易读的格式:
var d = new Date().toDateString(); //Wed Dec 30 2020
toLocaleString()
new Date().toLocaleString() //2021/1/5 下午6:47:43
日期获取方法
getTime() 方法
getTime() 方法返回自 1970 年 1 月 1 日以来的毫秒数:
var d = new Date().getTime(); //1609320944129
getFullYear() 方法
getFullYear() 方法以四位数字形式返回日期年份:
var d = new Date().getFullYear(); //2020
getMonth() 方法
getMonth() 以数字(0-11)返回日期的月份:
var d = new Date().getMonth(); //我12月份记得,所以结果是11
在 JavaScript 中,第一个月(1 月)是月号 0,因此 12 月返回月号 11。
您可以使用名称数组,并使用 getMonth() 将月份作为名称返回:
var d = new Date(); var months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; months[d.getMonth()]; //"December"(其实就是用的索引判断是第几个)
getDate() 方法
getDate() 方法以数字(1-31)返回日期的日:
var d = new Date().getDate(); // 30
getHours() 方法
getHours() 方法以数字(0-23)返回日期的小时数:
var d = new Date().getHours(); //20
getMinutes() 方法
getMinutes() 方法以数字(0-59)返回日期的分钟数:
var d = new Date().getMinutes(); //40
getSeconds() 方法
getSeconds() 方法以数字(0-59)返回日期的秒数:
var d = new Date().getSeconds(); //57
getMilliseconds() 方法
getMilliseconds() 方法以数字(0-999)返回日期的毫秒数:
var d = new Date().getMilliseconds(); //559
getDay() 方法
getDay() 方法以数字(0-6)返回日期的星期名(weekday):
var d = new Date().getDay(); //4
设置日期方法
使用“设置日期”方法可以设置日期对象的日期值(年、月、日、小时、分钟、秒、毫秒)。
setFullYear() 方法
setFullYear() 方法设置日期对象的年份。这个例子设置为 2019年:
var d = new Date(); //Tue Dec 31 2019 09:52:05 GMT+0800 (中国标准时间)
setFullYear() 方法可以选择设置月和日:
var d = new Date(); d.setFullYear(2020, 11, 3); //Thu Dec 03 2020 09:54:15 GMT+0800 (中国标准时间)
setMonth() 方法
setMonth() 方法设置日期对象的月份(0-11):
var d = new Date(); d.setMonth(11); //设置12月 //Thu Dec 31 2020 10:13:50 GMT+0800 (中国标准时间)
setDate() 方法
setDate() 方法设置日期对象的日(1-31):
var d = new Date(); d.setDate(15); //Tue Dec 15 2020 10:16:17 GMT+0800 (中国标准时间)
setDate() 方法也可用于将天数添加到日期:
var d = new Date(); d.setDate(d.getDate() + 50); //Fri Feb 19 2021 10:16:32 GMT+0800 (中国标准时间)
setHours() 方法
setHours() 方法设置日期对象的小时(0-23):
var d = new Date(); d.setHours(22); Thu Dec 31 2020 22:39:38 GMT+0800 (中国标准时间)
setMinutes() 方法
setMinutes() 方法设置日期对象的分钟(0-59):
var d = new Date(); d.setMinutes(30); //Thu Dec 31 2020 13:30:02 GMT+0800 (中国标准时间)
setSeconds() 方法
setSeconds() 方法设置日期对象的秒数(0-59):
var d = new Date(); d.setSeconds(30); //Thu Dec 31 2020 13:42:30 GMT+0800 (中国标准时间)
日期的比较
var today, someday, text; today = new Date(); someday = new Date(); someday.setFullYear(2049, 0, 16); if (someday > today) { text = "今天在 2049 年 1 月 16 日之前"; } else { text = "今天在 2049 年 1 月 16 日之后"; }
JavaScript 事件(在HTML上面触发的事件)
以下实例中,JavaScript 代码将修改 id=“demo” 元素的内容。
<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button> <p id="demo"></p>
在下个实例中,代码将修改自身元素的内容 (使用 this.innerHTML):
<button onclick="this.innerHTML=Date()">现在的时间是?</button>
通过函数调用
<button onclick="displayDate()">现在的时间是?</button>
常见的HTML事件
下面是一些常见的HTML事件的列表:
事件 | 描述 |
---|---|
onchange | HTML 元素改变 |
onclick | 用户点击 HTML 元素 |
onmouseover | 用户在一个HTML元素上移动鼠标 |
onmouseout | 用户从一个HTML元素上移开鼠标 |
onkeydown | 用户按下键盘按键 |
onload | 浏览器已完成页面的加载 |
运算符!
算术运算符
y=5,下面的表格解释了这些算术运算符:
如果把数字与字符串相加,结果将成为字符串!
运算符 | 描述 | 例子 | x 运算结果 | y 运算结果 |
---|---|---|---|---|
+ | 加法 | x=y+2 | 7 | 5 |
- | 减法 | x=y-2 | 3 | 5 |
* | 乘法 | x=y*2 | 10 | 5 |
/ | 除法 | x=y/2 | 2.5 | 5 |
% | 取模(余数) | x=y%2 | 1 | 5 |
++ | 自增 | x=++y | 6 | 6 |
x=y++ | 5 | 6 | ||
– | 自减 | x=–y | 4 | 4 |
x=y– | 5 | 4 |
赋值运算符
给定 x=10 和 y=5,下面的表格解释了赋值运算符:
运算符 | 例子 | 等同于 | 运算结果 |
---|---|---|---|
= | x=y | x=5 | |
+= | x+=y | x=x+y | x=15 |
-= | x-=y | x=x-y | x=5 |
*= | x*=y | x=x*y | x=50 |
/= | x/=y | x=x/y | x=2 |
%= | x%=y | x=x%y | x=0 |
比较运算符
比较运算符在逻辑语句中使用,以测定变量或值是否相等。
x=5,下面的表格解释了比较运算符:
运算符 | 描述 | 比较 | 返回值 |
---|---|---|---|
== | 等于 | x==8 | false |
x==5 | true | ||
=== | 绝对等于(值和类型均相等) | x===“5” | false |
x===5 | true | ||
!= | 不等于 | x!=8 | true |
!== | 不绝对等于(值和类型有一个不相等,或两个都不相等) | x!==“5” | true |
x!==5 | |||
> | 大于 | x>8 | false |
< | 小于 | x<8 | true |
>= | 大于或等于 | x>=8 | false |
<= | 小于或等于 | x<=8 | true |
逻辑运算符
逻辑运算符用于测定变量或值之间的逻辑。
给定 x=6 以及 y=3,下表解释了逻辑运算符:
运算符 | 描述 | 例子 |
---|---|---|
&&(短路与) | and | (x < 10 && y > 1) 为 true |
||(短路或) | or | (x5 || y5) 为 false |
! | not | !(x==y) 为 true |
& | 逻辑与 | |
| | 逻辑或 |
三元运算
variablename=bool?value1:value2
bool==true 时 variablename = value1
bool==false 时 variablename = value2
也可拼接成为四元运算符
name = bool1?value1:(bool2?value3:value2)
甚至更多,但是不推荐,过长时影响阅读
if…Else 语句
if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码
if…else 语句 - 当条件为 true 时执行代码,当条件为 false 时执行其他代码
if…else if…else 语句- 使用该语句来选择多个代码块之一来执行
switch语句
请使用 switch 语句来选择要执行的多个代码块之一。
switch(n) { case 1: 执行代码块 1 break; case 2: 执行代码块 2 break; default: 与 case 1 和 case 2 不同时执行的代码 }
工作原理:首先设置表达式 n(通常是一个变量)。随后表达式的值会与结构中的每个 case 的值做比较。如果存在匹配,则与该 case 关联的代码块会被执行。请使用 break 来阻止代码自动地向下一个 case 运行。
for循环
下面是 for 循环的语法:
for (*语句 1*; *语句 2*; *语句 3*) { *被执行的代码块* }
语句 1 (代码块)开始前执行
语句 2 定义运行循环(代码块)的条件
语句 3 在循环(代码块)已被执行之后执行
示例:
for (var i=0; i<5; i++) { x=x + "该数字为 " + i + "<br>"; }
For/In 循环
示例:
var person={fname:"Bill",lname:"Gates",age:56}; for (x in person) // x 为属性名 { txt=txt + person[x]; }
while 循环
while 循环会在指定条件为真时循环执行代码块。
while (条件) { 需要执行的代码 }
do/while 循环
do/while 循环是 while 循环的变体。该循环会在检查条件是否为真之前执行一次代码块,然后如果条件为真的话,就会重复这个循环。
do { x=x + "The number is " + i + "<br>"; i++; } while (i<5);
JavaScript break 和 continue 语句
break 语句
break 语句可用于跳出循环。
break 语句跳出循环后,会继续执行该循环之后的代码(如果有的话):
for (i=0;i<10;i++) { if (i==3)break; x=x + "The number is " + i + "<br>"; }
continue 语句
continue 语句中断循环中的迭代,如果出现了指定的条件,然后继续循环中的下一个迭代。 该例子跳过了值 3
for (i=0;i<=10;i++) { if (i==3) continue; x=x + "The number is " + i + "<br>"; }
JavaScript typeof, null, 和 undefined
typeof操作符
你可以使用 typeof 操作符来检测变量的数据类型。
typeof "John" // 返回 string typeof 3.14 // 返回 number typeof false // 返回 boolean typeof [1,2,3,4] // 返回 object typeof {name:'John', age:34} // 返回 object
null
在 JavaScript 中 null 表示 “什么都没有”。
null是一个只有一个值的特殊类型。表示一个空对象引用。
用 typeof 检测 null 返回是object。
你可以设置为 null 来清空对象:
var person = null; // 值为 null(空), 但类型为对象
undefined
在 JavaScript 中, undefined 是一个没有设置值的变量。
typeof 一个没有值的变量会返回 undefined。
var person; // 值为 undefined(空), 类型是undefined
undefined 和 null 的区别
null 和 undefined 的值相等,但类型不等: typeof undefined // undefined typeof null // object null === undefined // false null == undefined // true
1、定义
- (1)undefined:是所有没有赋值变量的默认值,自动赋值。
- (2)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。
2、何时使用null?
当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null。
JavaScript 类型转换
constructor 属性返回所有 JavaScript 变量的构造函数。
"John".constructor // 返回函数 String() { [native code] } (3.14).constructor // 返回函数 Number() { [native code] } false.constructor // 返回函数 Boolean() { [native code] } [1,2,3,4].constructor // 返回函数 Array() { [native code] } {name:'John', age:34}.constructor // 返回函数 Object() { [native code] } new Date().constructor // 返回函数 Date() { [native code] } function () {}.constructor // 返回函数 Function(){ [native code] }
你可以使用 constructor 属性来查看对象是否为数组 (包含字符串 “Array”):
function isArray(myArray) { return myArray.constructor.toString().indexOf("Array") > -1; }
将数字转换为字符串
全局方法 String() 可以将数字转换为字符串。
该方法可用于任何类型的数字,字母,变量,表达式:
String(x) // 将变量 x 转换为字符串并返回 String(123) // 将数字 123 转换为字符串并返回 String(100 + 23) // 将数字表达式转换为字符串并返回
Number 方法 toString() 也是有同样的效果。
x.toString() (123).toString() (100 + 23).toString()
将布尔值转换为字符串
全局方法 String() 可以将布尔值转换为字符串。
String(false) // 返回 "false" String(true) // 返回 "true"
Boolean 方法 toString() 也有相同的效果。
false.toString() // 返回 "false" true.toString() // 返回 "true"
其他的都差不多
自动转换类型
当 JavaScript 尝试操作一个 “错误” 的数据类型时,会自动转换为 “正确” 的数据类型。
以下输出结果不是你所期望的:
5 + null // 返回 5 null 转换为 0 "5" + null // 返回"5null" null 转换为 "null" "5" + 1 // 返回 "51" 1 转换为 "1" "5" - 1 // 返回 4 "5" 转换为 5
下表展示了使用不同的数值转换为数字(Number), 字符串(String), 布尔值(Boolean):
原始值 转换为数字 转换为字符串 转换为布尔值 false 0 “false” false true 1 “true” true 0 0 “0” false 1 1 “1” true “0” 0 “0” true “000” 0 “000” true “1” 1 “1” true NaN NaN “NaN” false Infinity Infinity “Infinity” true -Infinity -Infinity “-Infinity” true “” 0 “” false “20” 20 “20” true “Runoob” NaN “Runoob” true [ ] 0 “” true [20] 20 “20” true [10,20] NaN “10,20” true [“Runoob”] NaN “Runoob” true [“Runoob”,“Google”] NaN “Runoob,Google” true function(){} NaN “function(){}” true NaN “[object Object]” true null 0 “null” false undefined NaN “undefined” false
JavaScript 正则表达式
语法
/正则表达式主体/修饰符(可选) 实例: var patt = /runoob/i 实例解析: /runoob/i 是一个正则表达式。 runoob 是一个正则表达式主体 (用于检索)。 i 是一个修饰符 (搜索不区分大小写)。
使用字符串方法
在 JavaScript 中,正则表达式通常用于两个字符串方法 : search() 和 replace()。
search() 方法 用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。
replace() 方法 用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
search() 方法使用正则表达式
使用正则表达式搜索 “Runoob” 字符串,且不区分大小写:
var str = "Visit Runoob!"; var n = str.search(/Runoob/i);
输出结果为:
6
search() 方法使用字符串
search 方法可使用字符串作为参数。字符串参数会转换为正则表达式:
检索字符串中 “Runoob” 的子串:
var str = "Visit Runoob!"; var n = str.search("Runoob"); 输出结果:6
replace() 方法使用正则表达式
使用正则表达式且不区分大小写将字符串中的 Microsoft 替换为 Runoob
var str = 'Visit Microsoft!'; var txt = str.replace(/microsoft/i,"Runoob"); 输出结果为:Visit Runoob!
replace() 方法使用字符串
replace() 方法将接收字符串作为参数:
var str = 'Visit Microsoft!' var txt = str.replace("Microsoft","Runoob"); 输出结果为:Visit Runoob!
match()方法
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
在字符串中查找 "ain": var str="The rain in SPAIN stays mainly in the plain"; var n=str.match(/ain/g); n 输出数组结果值: ain,ain,ain
注意: match() 方法将检索字符串 String Object,以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配(就是只匹配到一个)。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
正则表达式修饰符
修饰符 可以在全局搜索中不区分大小写:
修饰符 | 描述 |
---|---|
i | 执行对大小写不敏感的匹配。 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
m | 执行多行匹配。 |
正则表达式模式
方括号用于查找某个范围内的字符:
表达式 | 描述 |
---|---|
[abc] | 查找方括号之间的任何字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
(x|y) | 查找任何以 | 分隔的选项。 |
[^abc] | 查找不在方括号内的字符 |
[A-z] | 查找从大写 A 到小写 z 范围内的字符,即所有大小写的字母。 |
元字符是拥有特殊含义的字符:
. | 查找单个字符,除了换行和行结束符 |
---|---|
\w | 查找单词字符 |
\W | 查找非单词字符 |
\d | 查找数字 |
\D | 查找非数字字符 |
\s | 查找空白字符 |
\S | 查找非空白字符 |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
\0 | 查找 NUL字符 |
\n | 查找换行符 |
\f | 查找换页符 |
\r | 查找回车符 |
\t | 查找制表符 |
\v | 查找垂直制表符 |
\xxx | 查找以八进制数 xxxx 规定的字符 |
\xdd | 查找以十六进制数 dd 规定的字符 |
\uxxxx | 查找以十六进制 xxxx规定的 Unicode 字符 |
量词:
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n | 匹配包含 x 个 n 的序列的字符串 |
n | 匹配包含最少 x 个、最多 y 个 n 的序列的字符串 |
n | 匹配包含至少 x 个 n 的序列的字符串 |
重复类量词总是出现在它们所作用的字符或子表达式后面。如果想作用于多个字符,需要使用小括号把它们包裹在一起形成一个子表达式。
惰性匹配
重复类量词都具有贪婪性,在条件允许的前提下,会匹配尽可能多的字符。
?、{n} 和 {n,m} 重复类具有弱贪婪性,表现为贪婪的有限性。
*、+ 和 {n,} 重复类具有强贪婪性,表现为贪婪的无限性。
越是排在左侧的重复类量词匹配优先级越高。下面示例显示当多个重复类量词同时满足条件时,会在保证右侧重复类量词最低匹配次数基础上,使最左侧的重复类量词尽可能占有所有字符。
如:
var s = "<html><head><title></title></head><body></body></html>"; var r = /(<.*>)(<.*>)/ var a = s.match(r);//左侧表达式匹配"<html><head><title></title></head><body></body> console.log(a[1]); console.log(a[2]); //右侧表达式匹配“</html>”
与贪婪匹配相反,惰性匹配将遵循另一种算法:在满足条件的前提下,尽可能少的匹配字符。定义惰性匹配的方法:在重复类量词后面添加问号?限制词。贪婪匹配体现了最大化匹配原则,惰性匹配则体现最小化匹配原则。
下面示例演示了如何定义匹配模式。
var s = "<html><head><title></title></head><body></body></html>"; var r = /<.*?>/ var a = s.match(r); //返回单个元素数组["<html>"]
在上面示例中,对于正则表达式 /<.*?>/ 来说,它可以返回匹配字符串 “<>”,但是为了能够确保匹配条件成立,在执行中还是匹配了带有 4 个字符的字符串“html”。惰性取值不能够以违反模式限定的条件而返回,除非没有找到符合条件的字符串,否则必须满足它。
边界量词
边界就是确定匹配模式的位置,如字符串的头部或尾部,具体说明如表所示。
量词 说明 ^ 匹配开头,在多行检测中,会匹配一行的开头 $ 匹配结尾,在多行检测中,会匹配一行的结尾 下面代码演示如何使用边界量词。先定义字符串:
var s = "how are you"
- 匹配最后一个单词
var r = /\w+$/; var a = s.match(r); //返回数组["you"]
- 匹配第一个单词
var r = /^\w+/; var a = s.match(r); //返回数组["how"]
正向声明
指定匹配模式后面的字符必须被匹配,但又不返回这些字符。语法格式如下:
匹配模式 (?= 匹配条件)
声明包含在小括号内,它不是分组,因此作为子表达式。
下面代码定义一个正前向声明的匹配模式。
var s = "one:1;two=2"; var r = /\w*(?==)/; //使用正前向声明,指定执行匹配必须满足的条件 var a = s.match(r); //返回数组["two"]
在上面示例中,通过
?==
锚定条件,指定只有在 \w* 所能够匹配的字符后面跟随一个等号字符,才能够执行 \w* 匹配。所以,最后匹配的字符串“two”,而不是字符串“one”。
反向声明
与正向声明匹配相反,指定接下来的字符都不必被匹配。语法格式如下:
匹配模式(?! 匹配条件)
下面代码定义一个反前向生命的匹配模式。
var s = "one:1;two=2"; var r = /\w*(?!=)/; //使用正前向声明,指定执行匹配不必满足的条件 var a = s.match(r); //返回数组["one"]
在上面示例中,通过
?!=
锚定条件,指定只有在“\w*”所能够匹配的字符后面不跟随一个等号字符,才能够执行 \w*匹配。所以,最后匹配的是字符串“one”,而不是字符串“two”。
子表达式
使用小括号可以对字符模式进行任意分组,在小括号内的字符串表示子表达式,也称为子模式。子表达式具有独立的匹配功能,保存独立的匹配结果;同时,小括号后的量词将会作用于整个子表达式。
通过分组可以在一个完整的字符模式中定义一个或多个子模式。当正则表达式成功地匹配目标字符串后,也可以从目标字符串中抽出与子模式相匹配的子内容。
示例
在下面代码中,不仅能匹配出每个变量声明,同时还抽出每个变量及其值。
var s = "ab=21, bc=45, cd=43"; var r = /(\w+)=(\d*)/g; while (a = r.exec(s)) { console.log(a); //返回类似["ab=21","bc=45","cd=43"]三个数组 }
错误处理 - throw、try 、catch和finally
try 语句测试代码块的错误。
catch 语句处理错误。
throw 语句创建自定义错误。
finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行。
try 、catch和finally
try 语句允许我们定义在执行时进行错误测试的代码块。
catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
JavaScript 语句 try 和 catch 是成对出现的。
try { ... //异常的抛出 } catch(e) { ... //异常的捕获与处理 }finally{ //finally 语句不论之前的 try 和 catch 中是否产生异常都会执行该代码块。(可不写,看需求) }
Throw 语句
throw 语句允许我们创建自定义错误。
正确的技术术语是:创建或抛出异常(exception)。
如果把 throw 与 try 和 catch 一起使用,那么您能够控制程序流,并生成自定义的错误消息。
throw exception 如 throw "值为空"; 而此时的catch(err)中的err的值为"值为空"
this 关键字
面向对象语言中 this 表示 “当前对象” 的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
- 在方法中,this 表示该方法所属的对象。
- 如果单独使用,this 表示全局对象。
- 在函数中,this 表示全局对象。
- 在函数中,在严格模式下,this 是未定义的(undefined)。
- 在事件中,this 表示接收事件的元素。
- 类似 call() 和 apply() 方法可以将 this 引用到任何对象。
对象方法中的 this
在对象方法中, this 指向调用它所在方法的对象。
在实例中,this 表示 person 对象。
fullName 方法所属的对象就是 person。
var person = { firstName: "John", lastName : "Doe", id : 5566, fullName : function() { return this.firstName + " " + this.lastName; } };
单独使用 this
单独使用 this,则它指向全局(Global)对象。
在浏览器中,window 就是该全局对象为 [object Window]:
var x = this;
事件中的 this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素:
<button onclick="this.style.display='none'"> 点我后我就消失了 </button>
改变this的call()、apply()、bind() 的用法
其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解!
先看明白下面:
例 1
obj.objAge; // 17
obj.myFun() // 小张年龄 undefined
例 2
shows() // 盲僧
比较一下这两者 this 的差别,第一个打印里面的 this 指向 obj,第二个全局声明的 shows() 函数 this 是 window ;
1,call()、apply()、bind() 都是用来重定义 this 这个对象的!
如:
obj.myFun.call(db); // 德玛年龄 99
obj.myFun.apply(db); // 德玛年龄 99
obj.myFun.bind(db)(); // 德玛年龄 99
以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行。
2,对比call 、bind 、 apply 传参情况下
obj.myFun.call(db,'成都','上海'); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.apply(db,['成都','上海']); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,'成都','上海')(); // 德玛 年龄 99 来自 成都去往上海
obj.myFun.bind(db,['成都','上海'])(); // 德玛 年龄 99 来自 成都, 上海去往 undefined
3.bind
- bind:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8
fn.call(obj, 1, 2); // 改变fn中的this,并且把fn立即执行
fn.bind(obj, 1, 2); // 改变fn中的this,fn并不执行
1212
this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined
document.onclick = fn.call(obj);
11
bind会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行
document.onclick = fn.bind(obj);
微妙的差距!
从上面四个结果不难看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,‘成都’, … ,‘string’ )。
apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,[‘成都’, …, ‘string’ ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!
JavaScript JSON
JSON 是用于存储和传输数据的格式。
JSON 通常用于服务端向网页传递数据 。
JSON 语法规则
数据为 键/值 对。
数据由逗号分隔。
大括号保存对象
方括号保存数组
JSON 数据 - 一个名称对应一个值
JSON 数据格式为 键/值 对,就像 JavaScript 对象属性。
键/值对包括字段名称(在双引号中),后面一个冒号,然后是值:
“name”:“Runoob”
JSON 对象
JSON 对象保存在大括号内。
就像在 JavaScript 中, 对象可以保存多个 键/值 对:
{"name":"Runoob", "url":"www.runoob.com"}
JSON 数组
JSON 数组保存在中括号内。
就像在 JavaScript 中, 数组可以包含对象:
"sites":[ {"name":"Runoob", "url":"www.runoob.com"}, {"name":"Google", "url":"www.google.com"}, {"name":"Taobao", "url":"www.taobao.com"} ]
JSON 字符串转换为 JavaScript 对象(JSON.parse())
JSON.parse() 方法用于将一个 JSON 字符串转换为对象。
JSON.parse(text[, reviver])
参数说明:
- **text:**必需, 一个有效的 JSON 字符串。
- reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
var text = '{"employees":[' + '{"name":"菜鸟教程","site":"http://www.runoob.com" },' + '{"name":"Google","site":"http://www.Google.com" },' + '{"name":"Taobao","site":"http://www.taobao.com" }]}'; obj = JSON.parse(text); obj.employees[1].name;//Google obj.employees[1].site;//http://www.Google.com
使用可选参数:
JSON.parse('{"p": 5}', function(key, value) { if (key === '') { return value; } else{ return value * 2; } }); //{p:10} JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', function(key, value) { console.log(key); // 输出当前属性,最后一个为 "" return value; // 返回修改的值 }); //124653
JavaScript 对象转换为JSON 字符串 (JSON.stringify())
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify(value[, replacer[, space]])
参数说明:
value:
必需, 要转换的 JavaScript 值(通常为对象或数组)。
replacer:
可选。用于转换结果的函数或数组。
如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:“”。
如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。
space:
可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。
var str = {"name":"菜鸟教程", "site":"http://www.runoob.com"} str_pretty1 = JSON.stringify(str) //{"name":"菜鸟教程","site":"http://www.runoob.com"} str_pretty2 = JSON.stringify(str, null, 4) //使用四个空格缩进 //{ // "name": "菜鸟教程", // "site": "http://www.runoob.com" //}
Math 对象
Math 属性(常量)
JavaScript 提供了可由 Math 对象访问的 8 个数学常量:
Math.E // 返回欧拉指数(Euler's number) Math.PI // 返回圆周率(PI) Math.SQRT2 // 返回 2 的平方根 Math.SQRT1_2 // 返回 1/2 的平方根 Math.LN2 // 返回 2 的自然对数 Math.LN10 // 返回 10 的自然对数 Math.LOG2E // 返回以 2 为底的 e 的对数(约等于 1.414) Math.LOG10E // 返回以 10 为底的 e 的对数(约等于0.434)
Math 方法
abs(x) | 返回 x 的绝对值 |
---|---|
acos(x) | 返回 x 的反余弦值,以弧度计 |
asin(x) | 返回 x 的反正弦值,以弧度计 |
atan(x) | 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。 |
atan2(y,x) | 返回从 x 轴到点 (x,y) 的角度 |
ceil(x) | 对 x 进行上舍入 |
cos(x) | 返回 x 的余弦 |
exp(x) | 返回 Ex 的值 |
floor(x) | 对 x 进行下舍入 |
log(x) | 返回 x 的自然对数(底为e) |
max(x,y,z,…,n) | 返回最高值 |
min(x,y,z,…,n) | 返回最低值 |
pow(x,y) | 返回 x 的 y 次幂 |
random() | 返回 0 ~ 1 之间的随机数 |
round(x) | 把 x 四舍五入为最接近的整数 |
sin(x) | 返回 x(x 以角度计)的正弦 |
sqrt(x) | 返回 x 的平方根 |
tan(x) | 返回角的正切 |
Math.random() 返回 0(包括) 至 1(不包括) 之间的随机数:
Math.random() 与 Math.floor() 一起使用用于返回随机整数。
//公式 //Math.floor(Math.random()*(m-n+1)+n) Math.floor(Math.random() * 10); // 返回 0 至 9 之间的数
表单验证
以下实例代码用于判断表单字段(fname)值是否存在, 如果不存在,就弹出信息,阻止表单提交:
<form name="myForm" action="demo_form.php" onsubmit="return validateForm()" method="post"> 名字: <input type="text" name="fname"> <input type="submit" value="提交"> </form> function validateForm() { var x = document.forms["myForm"]["fname"].value; if (x == null || x == "") { alert("需要输入名字。"); return false; } }
HTML中新增(表单自动验证)
HTML 表单验证也可以通过浏览器来自动完成。
如果表单字段 (fname) 的值为空, required 属性会阻止表单提交:
属性 描述 disabled 规定输入的元素不可用 max 规定输入元素的最大值 min 规定输入元素的最小值 pattern 规定输入元素值的模式 required 规定输入元素字段是必需的 type 规定输入元素的类型 约束验证 CSS 伪类选择器
选择器 描述 :disabled 选取属性为 “disabled” 属性的 input 元素 :invalid 选取无效的 input 元素 :optional 选择没有"required"属性的 input 元素 :required 选择有"required"属性的 input 元素 :valid 选取有效值的 input 元素 实例
如果表单字段 (fname) 的值为空, required 属性会阻止表单提交:
<form action="demo_form.php" method="post"> <input type="text" name="fname" required="required"> <input type="submit" value="提交"> </form>
构造 Promise
现在我们新建一个 Promise 对象:
new Promise(function (resolve, reject) { // 要做的事情...这里面是起始函数,Promise 对象一创建就会执行。 });
优雅地书写复杂的异步任务
原:
setTimeout(function () { console.log("First"); setTimeout(function () { console.log("Second"); setTimeout(function () { console.log("Third"); }, 3000); }, 4000); }, 1000);
现在我们用 Promise 来实现同样的功能:
new Promise(function (resolve, reject) { setTimeout(function () { console.log("First"); resolve(); }, 1000); }).then(function () { return new Promise(function (resolve, reject) { setTimeout(function () { console.log("Second"); resolve(); }, 4000); }); }).then(function () { setTimeout(function () { console.log("Third"); }, 3000); }); //First //Second //Third
resolve代表成功,reject代表失败,
resolve会跳到then,reject会跳到catch,finally都会执行
JavaScript HTML DOM
查找 HTML 元素
通过 id 查找 HTML 元素
在 DOM 中查找 HTML 元素的最简单的方法,是通过使用元素的 id。
本例查找 id=“intro” 元素:
var x=document.getElementById("intro");
如果找到该元素,则该方法将以对象(在 x 中)的形式返回该元素。
如果未找到该元素,则 x 将包含 null。
通过标签名查找 HTML 元素
本例查找 id=“main” 的元素,然后查找 id=“main” 元素中的所有
元素:
var x=document.getElementById("main"); var y=x.getElementsByTagName("p"); ////在控制台我们可以看到原型proto为htmlcollection,是伪数组
通过类名找到 HTML 元素
本例来查找 class=“intro” 的元素:
var x=document.getElementsByClassName("intro");
getElementsByClassName() 方法返回文档中所有指定类名的元素集合,作为 NodeList 对象。
NodeList 对象代表一个有顺序的节点列表。NodeList 对象 我们可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。
提示: 你可以使用 NodeList 对象的 length 属性来确定指定类名的元素个数,并循环各个元素来获取你需要的那个元素。
伪数组转为真数组方法
对DOM元素进行map、forEach操作时候需要进行遍历,伪数组遍历会报错:‘elem.map is not a function’,为了避免这个问题,需要进行转换。
ES5 转为真数组
Array.prototype.slice.call(元素对象)
let elem2 = Array.prototype.slice.call(elem)
Array.prototype.slice.apply(元素对象)
let elem2 = Array.prototype.slice.apply(elem)
Array.prototype.slice.bind(元素对象)()
let elem2 = Array.prototype.slice.bind(elem)()
ES6 转为真数组
Array.from(元素对象)
let elem2 = Array.from(elem)
改变 HTML
改变 HTML 输出流
JavaScript 能够创建动态的 HTML 内容:
今天的日期是: Sat Jan 02 2021 00:14:13 GMT+0800 (中国标准时间)
在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容。
<!DOCTYPE html> <html> <body> <script> document.write(Date()); </script> </body> </html>
绝对不要在文档(DOM)加载完成之后使用 document.write()。
这会覆盖该文档
改变 HTML 内容
修改 HTML 内容的最简单的方法是使用 innerHTML 属性。
如需改变 HTML 元素的内容,请使用这个语法:
document.getElementById(id).innerHTML=新的 HTML
本例改变了
元素的内容:
<html> <body> <p id="p1">Hello World!</p> <script> document.getElementById("p1").innerHTML="新文本!"; </script> </body> </html>
改变 HTML 属性
如需改变 HTML 元素的属性,请使用这个语法:
document.getElementById(id).attribute=新属性值
本例改变了
元素的 src 属性:
<!DOCTYPE html> <html> <body> <img id="image" src="smiley.gif"> <script> document.getElementById("image").src="landscape.jpg"; </script> </body> </html>
改变CSS
改变 HTML 样式
如需改变 HTML 元素的样式,请使用这个语法:
document.getElementById(*id*).style.property=新样式
下面的例子会改变
元素的样式:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body> <p id="p1">Hello World!</p> <p id="p2">Hello World!</p> <script> document.getElementById("p2").style.color="blue"; document.getElementById("p2").style.fontFamily="Arial"; document.getElementById("p2").style.fontSize="larger"; </script> <p>以上段落通过脚本修改。</p> </body> </html>
使用事件
HTML DOM 允许我们通过触发事件来执行代码。
比如以下事件:
- 元素被点击。
- 页面加载完成。
- 输入框被修改。
- ……
本例改变了 id=“id1” 的 HTML 元素的样式,当用户点击按钮时:
<!DOCTYPE html> <html> <body> <h1 id="id1">我的标题 1</h1> <button type="button" onclick="document.getElementById('id1').style.color='red'"> 点我!</button> </body> </html>
HTML DOM 事件
我们可以在事件发生时执行 JavaScript,比如当用户在 HTML 元素上点击时。
如需在用户点击某个元素时执行代码,请向一个 HTML 事件属性添加 JavaScript 代码:
onclick=JavaScript
HTML 事件的例子:
- 当用户点击鼠标时
- 当网页已加载时
- 当图像已加载时
- 当鼠标移动到元素上时
- 当输入字段被改变时
- 当提交 HTML 表单时
- 当用户触发按键时
在本例中,当用户在
元素上点击时,会改变其内容:
<!DOCTYPE html> <html> <body> <h1 onclick="this.innerHTML='Ooops!'">点击文本!</h1> </body> </html>
本例从事件处理器调用一个函数:
<!DOCTYPE html> <html> <head> <script> function changetext(id) { id.innerHTML="Ooops!"; } </script> </head> <body> <h1 onclick="changetext(this)">点击文本!</h1> </body> </html>
HTML DOM EventListener
addEventListener() 方法
在用户点击按钮时触发监听事件:
document.getElementById("myBtn").addEventListener("click", displayDate);
addEventListener() 方法用于向指定元素添加事件句柄。
addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。
你可以向一个元素添加多个事件句柄。
你可以向同个元素添加多个同类型的事件句柄,如:两个 “click” 事件。
你可以向任何 DOM 对象添加事件监听,不仅仅是 HTML 元素。如: window 对象。
addEventListener() 方法可以更简单的控制事件(冒泡与捕获)。
当你使用 addEventListener() 方法时, JavaScript 从 HTML 标记中分离开来,可读性更强, 在没有控制HTML标记时也可以添加事件监听。
你可以使用 removeEventListener() 方法来移除事件的监听。
语法
element.addEventListener(event, function, useCapture);
第一个参数是事件的类型 (如 “click” 或 “mousedown”).
第二个参数是事件触发后调用的函数。
第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。
注意:不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
向原元素添加事件句柄
当用户点击元素时弹出 “Hello World!” :
element.addEventListener("click", myFunction); function myFunction() { alert ("Hello World!"); }
向同一个元素中添加多个事件句柄
addEventListener() 方法允许向同一个元素添加多个事件,且不会覆盖已存在的事件:
element.addEventListener("click", myFunction); element.addEventListener("click",mySecondFunction);
你可以向同个元素添加不同类型的事件:
element.addEventListener("mouseover", myFunction); element.addEventListener("click",mySecondFunction); element.addEventListener("mouseout",myThirdFunction);
向 Window 对象添加事件句柄
addEventListener() 方法允许你在 HTML DOM 对象添加事件监听, HTML DOM 对象如: HTML 元素, HTML 文档, window 对象。或者其他支出的事件对象如: xmlHttpRequest 对象。
当用户重置窗口大小时添加事件监听:
window.addEventListener("resize", function(){ document.getElementById("demo").innerHTML=sometext;});
传递参数
当传递参数值时,使用"匿名函数"调用带参数的函数:
element.addEventListener("click", function(){ myFunction(p1, p2); });
事件冒泡或事件捕获
事件传递有两种方式:冒泡与捕获。
事件传递定义了元素事件触发的顺序。 如果你将
元素插入到
元素中,用户点击元素, 哪个元素的 “click” 事件先被触发呢?
在 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即:
元素的点击事件先触发,然后会触发
元素的点击事件。在 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即:
元素的点击事件先触发 ,然后再触发元素的点击事件。
addEventListener() 方法可以指定 "useCapture" 参数来设置传递类型: addEventListener(event,function, useCapture); 默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。 document.getElementById("myDiv").addEventListener("click", myFunction, true);
removeEventListener() 方法
removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄:
element.removeEventListener("mousemove", myFunction);
HTML DOM 元素 (节点)
创建标签
var dom = document.createElement('标签名')
添加标签
父节点.appendChild(子节点);
实例:
var div_father = document.createElement("div"); var div_child = document.createElement("div"); div_father.appendChild(div_child) //把div_child添加到div_father里,div_father也可以是已存在元素
以上的实例我们使用了 appendChild() 方法,它用于添加新元素到尾部。
创建新的 HTML 元素 (节点) - insertBefore()
如果我们需要将新元素添加到开始位置,可以使用 insertBefore() 方法:
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var para = document.createElement("p"); var node = document.createTextNode("这是一个新的段落。"); para.appendChild(node); var element = document.getElementById("div1"); var child = document.getElementById("p1"); element.insertBefore(para, child); </script>
移除已存在的元素
要移除一个元素,你需要知道该元素的父元素。
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var parent = document.getElementById("div1"); var child = document.getElementById("p1"); parent.removeChild(child); </script>
替换 HTML 元素 - replaceChild()
我们可以使用 replaceChild() 方法来替换 HTML DOM 中的元素。
<div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另外一个段落。</p> </div> <script> var para = document.createElement("p"); var node = document.createTextNode("这是一个新的段落。"); para.appendChild(node); var parent = document.getElementById("div1"); var child = document.getElementById("p1"); parent.replaceChild(para, child); </script>
HTML DOM 节点列表
NodeList 对象是一个从文档中获取的节点列表 (集合) 。
NodeList 对象类似 HTMLCollection 对象。
一些旧版本浏览器中的方法(如:getElementsByClassName())返回的是 NodeList 对象,而不是 HTMLCollection 对象。
所有浏览器的 childNodes 属性返回的是 NodeList 对象。
大部分浏览器的 querySelectorAll() 返回 NodeList 对象。
以下代码选取了文档中所有的
节点:
var myNodeList = document.querySelectorAll("p");
NodeList 中的元素可以通过索引(以 0 为起始位置)来访问。
访问第二个
元素可以是以下代码:
y = myNodeList[1];
NodeList 对象 length 属性
NodeList 对象 length 属性定义了节点列表中元素的数量。
var myNodelist = document.querySelectorAll("p"); document.getElementById("demo").innerHTML = myNodelist.length;
HTMLCollection vs. NodeList
综上所述,进行归纳,并回答文章开头提出的疑问。
HTMLCollection
和NodeList
的共同点显而易见:
- 都是类数组对象,都有
length
属性- 都有共同的方法:
item
,可以通过item(index)
或者item(id)
来访问返回结果中的元素- 都是实时变动的(live),document上的更改会反映到相关对象上(例外:
document.querySelectorAll
返回的NodeList
不是实时的)HTMLCollection
和NodeList
的区别是:
NodeList
可以包含任何节点类型,HTMLCollection
只包含元素节点(elementNode),elementNode就是HTML中的标签HTMLCollection
比NodeList
多一项方法:namedItem
,可以通过传递id或name属性来获取节点信息Window - 浏览器对象模型
浏览器对象模型 (BOM) 使 JavaScript 有能力与浏览器"对话"。
Window 对象
所有浏览器都支持 window 对象。它表示浏览器窗口。
所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。
全局变量是 window 对象的属性。
全局函数是 window 对象的方法。
甚至 HTML DOM 的 document 也是 window 对象的属性之一:
window.document.getElementById("header");
与此同时:
document.getElementById("header");
Window 尺寸
有三种方法能够确定浏览器窗口的尺寸。
对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight - 浏览器窗口的内部高度(包括滚动条) window.innerWidth - 浏览器窗口的内部宽度(包括滚动条)
对于 Internet Explorer 8、7、6、5:
document.documentElement.clientHeight document.documentElement.clientWidth //或者 document.body.clientHeight document.body.clientWidth
实用的 JavaScript 方案(涵盖所有浏览器):
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; //是用 “或” 只会选取成立的那个 var h=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
Window open() 方法
open() 方法用于打开一个新的浏览器窗口或查找一个已命名的窗口。
window.open(URL,name,specs,replace)
参数 说明 URL 可选。打开指定的页面的URL。如果没有指定URL,打开一个新的空白窗口 name 可选。指定target属性或窗口的名称。支持以下值:_blank - URL加载到一个新的窗口。这是默认_parent - URL加载到父框架_self - URL替换当前页面_top - URL替换任何可加载的框架集name - 窗口名称 specs 可选。一个逗号分隔的项目列表。支持以下值: channelmode=yes|no|1|0是否要在影院模式显示 window。默认是没有的。仅限IE浏览器directories=yes|no|1|0是否添加目录按钮。默认是肯定的。仅限IE浏览器fullscreen=yes|no|1|0浏览器是否显示全屏模式。默认是没有的。在全屏模式下的 window,还必须在影院模式。仅限IE浏览器height=pixels窗口的高度。最小.值为100left=pixels该窗口的左侧位置location=yes|no|1|0是否显示地址字段.默认值是yesmenubar=yes|no|1|0是否显示菜单栏.默认值是yesresizable=yes|no|1|0是否可调整窗口大小.默认值是yesscrollbars=yes|no|1|0是否显示滚动条.默认值是yesstatus=yes|no|1|0是否要添加一个状态栏.默认值是yestitlebar=yes|no|1|0是否显示标题栏.被忽略,除非调用HTML应用程序或一个值得信赖的对话框.默认值是yestoolbar=yes|no|1|0是否显示浏览器工具栏.默认值是yestop=pixels窗口顶部的位置.仅限IE浏览器width=pixels窗口的宽度.最小.值为100 replace Optional.Specifies规定了装载到窗口的 URL 是在窗口的浏览历史中创建一个新条目,还是替换浏览历史中的当前条目。支持下面的值:true - URL 替换浏览历史中的当前条目。false - URL 在浏览历史中创建新的条目。 Window close() 方法
close() 方法用于关闭浏览器窗口。
下面的例子可关闭新的浏览器:
function openWin(){ myWindow=window.open("","","width=200,height=100"); myWindow.document.write("<p>这是'我的窗口'</p>"); } function closeWin(){ myWindow.close(); }
Window moveTo() 方法
moveTo() 方法可把窗口的左上角移动到一个指定的坐标。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> <script> function openWin(){ myWindow=window.open('','','width=200,height=100'); myWindow.document.write("<p>这是我的窗口</p>"); } function moveWin(){ myWindow.moveTo(0,0); myWindow.focus(); } </script> </head> <body> <input type="button" value="打开窗口" onclick="openWin()" /> <br><br> <input type="button" value="移动窗口" onclick="moveWin()" /> </body> </html>
Window resizeTo() 方法
方法用于把窗口大小调整为指定的宽度和高度。
参数 说明 width 必需的。设置窗口的宽度,以像素为单位 height 必需的。设置窗口的高度,以像素为单位 所有主要浏览器都支持 resizeTo() 方法
从 Firefox 7 开始,不能改变浏览器窗口的大小了,要依据下面的规则:
- 不能设置那些不是通过 window.open 创建的窗口或 Tab 的大小。
- 当一个窗口里面含有一个以上的 Tab 时,无法设置窗口的大小。
创建一个窗口, 设置宽度与高度为 500px:
var w=window.open('','', 'width=100,height=100'); w.resizeTo(500,500);
0版权归属: 胖头鱼许可协议: 本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
- 0
评论区