0%

JavaScript学习

配置环境

参考(254条消息) 教你快速使用VSCode编写HTML文件_vscode html_半生瓜のblog的博客-CSDN博客

完成html在VScode上运行

JS功能

  • 直接写入HTML输出流
  • 对事件的反应
  • 改变HTML内容
  • 改变HTML图像
  • 改变HTML样式
  • 验证输入

JS实例

JavaScript 实例 | 菜鸟教程 (runoob.com)

对象实例JavaScript 对象实例 | 菜鸟教程 (runoob.com)

注意点

开发者工具的使用

F12 - 开发者工具详解 - 知乎 (zhihu.com)

显示数据的方式

JavaScript没有任何打印或者输出的函数

avaScript 可以通过不同的方式来输出数据:

  • 使用 window.alert() 弹出警告框。
  • 使用 document.write() 方法将内容写到 HTML 文档中。
  • 使用 innerHTML 写入到 HTML 元素。
  • ▲使用 console.log() 写入到浏览器的控制台。

注意:console不会打断你页面的操作,如果用alert弹出来内容,那么页面就死了,但是console输出内容后你页面还可以正常操作。

注意:innerHTML很多情况下都优于document.write,其原因在于其允许更精确的控制要刷新页面的那一个部分。

判断数据类型

在 JavaScript 中有 6 种不同的数据类型:

  • string
  • number
  • boolean
  • object
  • function
  • symbol

3 种对象类型:

  • Object
  • Date
  • Array

2 个不包含任何值的数据类型:

  • null
  • undefined

用typeof()函数,但是typeof()函数不能区别array和object,使用Array.isArray()方法或者使用 instanceof 操作符

Object的null 和 undefined

JavaScript 对象是拥有属性和方法的数据

对象是容器/键值对的容器

注意:键的类型不一定是字符串,而是字符串或符号,一般类型都是转换成字符串(对象数字等类型),但是符号不会被强制转换。

在 JavaScript 中, null 用于对象, undefined 用于变量,属性和方法。

对象只有被定义才有可能为 null,否则为 undefined。

如果我们想测试对象是否存在,在对象还没定义时将会抛出一个错误。

错误的使用方式:

1
if (myObj !== null && typeof myObj !== "undefined") 

正确的方式是我们需要先使用 typeof 来检测对象是否已定义:

1
if (typeof myObj !== "undefined" && myObj !== null) 

“helloworld”还是new String(“helloworld”)

不要创建 String 对象。它会拖慢执行速度,并可能产生其他副作用

BUT 原始值字符串,如 “John”, 没有属性和方法(因为他们不是对象),原始值可以使用 JavaScript 的属性和方法,因为 JavaScript 在执行方法和属性时可以把原始值当作对象

转为布尔类型

其他数据类型转换为布尔类型的规则: null、undefined、0、NaN、空字符串转换为false,其他转化为 true

switch判断

switch 中 case的判断是===的判断,即数据类型和值的双重判断,这点要注意。

for循环特点

中间如有某些下标未被使用(即未被赋值),在遍历的时候,采用一般的 for 循环和 for…in 循环得到的结果不同。

for…in 循环会自动跳过那些没被赋值的元素,而 for 循环则不会,它会显示出 undefined

for…of功能

  • 循环一个生成器

  • 循环一个拥有enumerate属性的对象(普通对象不行,按对象所拥有的属性进行循环,可使用内置的Object.keys()方法)

    1
    2
    3
    for (var key of Object.keys(someObject)) {
    console.log(key + ": " + someObject[key]);
    }
  • 循环一个DOM collection(??)

  • 循环字符串

  • 循环类型化数组

  • 循环Map

  • 循环Set

4 种循环的适用场景:

  • for : 比较适合遍历数组,字符串等等。
  • for in : 比较适合遍历对象,遍历对象时使用这个再合适不过了。
  • while : while 的话,与 for 的使用场景差不多。唯一不同的是,遍历的条件必须满足。
  • do while : 至少执行一边的循环,遍历数组和字符串也是很方便。

标签与break、continue

break 的作用是跳出代码块, 所以 break 可以使用于循环和 switch 等

continue 的作用是进入下一个迭代, 所以 continue 只能用于循环的代码块。

代码块: 基本上是{}大括号之间

然后:

  1. 默认标签的情况(除了默认标签情况,其他时候必须要有名标签,否则会有惊喜)

当 break 和 continue 同时用于循环时,没有加标签,此时默认标签为当前”循环”的代码块。

当 break 用于 switch 时,默认标签为当前的 switch 代码块:

有名标签的情况

1
2
3
4
5
6
7
8
9
10
11
cars=["BMW","Volvo","Saab","Ford"];
list:
{
document.write(cars[0] + "");
document.write(cars[1] + "");
document.write(cars[2] + "");
break list;
document.write(cars[3] + "");
document.write(cars[4] + "");
document.write(cars[5] + "");
}

上述break list;会跳出list的代码块。如果将break换成continue会有惊喜,违反了明确中的第二点,因为list只是个普通代码块,而不是循环。除非list写成如下形式 list:

1
2
3
4
for(var i=0; i<10; ++i)
{
continue list;
}

有了标签,可以使用break和continue在多层循环的时候控制外层循环。

例如下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
outerloop:
for (var i = 0; i < 10; i++)
{
innerloop:
for (var j = 0; j < 10; j++)
{
if (j > 3)
{
break;
}
if (i == 2)
{
break innerloop;
}
if (i == 4)
{
break outerloop;
}
document.write("i=" + i + " j=" + j + "");
}
}

constructor属性

可以使用 constructor 属性来查看对象是否为某某

1
2
3
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}

字符串转数字

字符串转日期:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var str = "2019-12-25";
// 转换日期格式
str = str.replace(/-/g, '/'); // "2010/08/01";
// 创建日期对象
var date = new Date(str);
反之,日期类型转化为格式化的字符串:

//完整的格式化
var time2 = new Date().format("yyyy-MM-dd hh:mm:ss");
Date.prototype.format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
//处理年份
var reYear = /(y+)/;
var resultYear = reYear.exec(fmt);
if (resultYear)
{
var yearformatPart = resultYear[0];//匹配到的格式化字符
var yearVal = (this.getFullYear() + "").substr(4 - yearformatPart.length);
fmt = fmt.replace(yearformatPart, yearVal);
}
for (var k in o) {
var re = new RegExp("(" + k + ")");
var re = re.exec(fmt);
if (re) {
var Val = "" + o[k];//本次需要替换的数据
var formatPart = re[0];//匹配到的格式化字符
var replaceVal = (formatPart.length == 1) ? (Val) : (("00" + Val).substr(Val.length));
fmt = fmt.replace(formatPart, replaceVal);
}
}
return fmt;
}

特殊值判断

NaN 这个特殊的数值也可以使用 Object.is() 方法来判断。

并且在这个方法中还可以判断 +0-0

1
2
3
4
console.log(Object.is(NaN, NaN)); //true
console.log(Object.is(+0, -0)); //false
console.log(Object.is(+0, 0)); //true
console.log(Object.is(0, -0)); //false

正则式

JavaScript RegExp 对象 | 菜鸟教程 (runoob.com)

正则表达式表单验证实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*是否带有小数*/
function isDecimal(strValue ) {
var objRegExp= /^\d+\.\d+$/;
return objRegExp.test(strValue);
}

/*校验是否中文名称组成 */
function ischina(str) {
var reg=/^[\u4E00-\u9FA5]{2,4}$/; /*定义验证表达式*/
return reg.test(str); /*进行验证*/
}

/*校验是否全由8位数字组成 */
function isStudentNo(str) {
var reg=/^[0-9]{8}$/; /*定义验证表达式*/
return reg.test(str); /*进行验证*/
}

/*校验电话码格式 */
function isTelCode(str) {
var reg= /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/;
return reg.test(str);
}

/*校验邮件地址是否合法 */
function IsEmail(str) {
var reg=/^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
return reg.test(str);
}

正则捕获,转换时间格式:

1
2
3
4
5
6
7
8
const str = '20210426141823';
const s = str.replace(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/, (_, ...args) => {
const [year, month, day, h, d, s] = args;
return `${year}年${month}月${day} ${h}时${d}分${s}秒`
});

console.log(s);
// 2021年04月26 14时18分23秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* [reg 百度网盘链接匹配]
* 说明:匹配支持百度分享的两种链接格式
* 格式一:链接: https://pan.baidu.com/s/15gzY8h3SEzVCfGV1xfkJsQ 提取码: vsuw 复制这段内容后打开百度网盘手机App,操作更方便哦
* 格式二:http://pan.baidu.com/share/link?shareid=179436&uk=3272055266 提取码: vsuw 复制这段内容后打开百度网盘手机App,操作更方便哦
* 匹配出下载地址和提取码,并且还支持如果没有提取码,也能匹配出下载链接。
* @type {正则表达式}
* @return array 返回匹配成功的链接和地址
*/

function baiduDownLinkArr( string ){
var reg = /([http|https]*?:\/\/pan\.baidu\.com\/[(?:s\/){0,1}|(share)]*(?:[0-9a-zA-Z?=&])+)(?:.+:(?:\s)*)?([a-zA-Z]{4})?/;
console.log(reg.exec(string));
}

HTML5 表单属性

HTML5 表单属性 | 菜鸟教程 (runoob.com)

多表单使用同一验证函数问题

上面用 js 表单验证判断表单字段(fname)值是否存在,如果想多个表单都使用同一个函数调用,传入参数后功能会失效,希望有大佬能解决这个问题。

现在我在网上找到的替代方法如下:

1
2
3
4
5
6
7
function validateForm(form) {
var x = form.name.value;
if (x == null || x == "") {
alert("输入不能为空!");
return false;
}
}

所有表单调用时都使用:

1
onsubmit="return validateForm(this)"

经验证好使。

事件属性为什么有return func()

onsubmit=”return validateForm()” 为什么不是 onsubmit=”validateForm()” ??

onsubmit=”validateForm()” 能够调用 validateForm() 对表单进行验证,但是在验证不通过的情况下,并不能阻止表单提交。

onsubmit=”return validateForm()” 当验证不通过时,返回 false,可以阻止表单提交。

为何?

原来 onsubmit 属性就像是

这个 html 对象的一个方法名,其值(一字符串)就是其方法体,默认返回 true;

1
onsubmit="return validateForm()"

相当于:

1
2
3
Form.prototype.onsubmit = function() {
return validateForm()
};

这样复写了 onsubmit 的默认方法(默认返回 true),根据 validateForm() 的结果返回 true 或 false,当验证不通过时,返回 false,onsubmit=”return false;” 阻止表单提交。

伪数组

getElementsByTagName 和 getElementsByClassName 这两个方法查找多个 dom 元素,返回的是 htmlcollection 类型,是伪数组而不是真数组,故不能使用数组的方法。
我们可以使用数组原型配合 slice 方法,利用 call,apply,bind 方法将伪数组转为真数组。

1
2
3
4
5
6
7
8
9
10
11
var x=document.getElementById("main");
var y=x.getElementsByTagName("p");
console.log(y)//在控制台我们可以看到原型proto为htmlcollection,是伪数组
//伪数组转为真数组方法1
console.log(Array.prototype.slice.call(y))//在控制台我们可以看到原型proto为Array(0),是真数组

//伪数组转为真数组方法2
console.log(Array.prototype.slice.apply(y))//在控制台我们可以看到原型proto为Array(0),是真数组

//伪数组转为真数组方法3
console.log(Array.prototype.slice.bind(y)())//在控制台我们可以看到原型proto为Array(0),是真数组

一些疑问

Q:HTML输出流?JavaScript可以直接写入HTML输出流中,为什么只能在 HTML 输出中使用 document.write?在文档加载后使用该方法,会覆盖整个文档?

注意:绝对不要在文档(DOM)加载完成之后使用 document.write()。这会覆盖该文档。

Q:怎么在测试的时候把本地图片插入到HTML中?

比如本地文件名为 eg_mouse,本地地址为C:\Users\xushiyu\Desktop,插入语句<img src=”file://C:/Users/xushiyu/Desktop/eg_mouse.jpg”

注意三点

Q:问题分析:当JS文件放在head标签里中时,并且绑定了onclick事件,就出现了Uncaught TypeError: Cannot set properties of null (setting ‘onclick’)错误

原因:W3School中介绍浏览器先加载完按钮节点才执行JS,当浏览器自顶向下解析时,找不到onclick绑定的按钮节点了

解决方案(259条消息) 解决Uncaught TypeError: Cannot set property ‘onclick’ of null错误的方法_全栈工匠的博客-CSDN博客