@SovietPower
2022-06-11T21:08:13.000000Z
字数 14041
阅读 1343
学习笔记
作业部落链接:https://www.zybuluo.com/SovietPower/note/1820040
参考:
https://www.runoob.com/js/js-tutorial.html
https://www.w3school.com.cn/js/index.asp
JavaScript是一种轻量级的编程语言,是可插入HTML页面的编程代码。
HTML定义了网页的内容,CSS描述了网页的布局,JavaScript控制了网页的行为。
在HTML中,JavaScript代码必须位于<script>
与</script>
标签之间。
<script>
可使用type属性:<script type="text/javascript">
指定脚本语言为JS,但不是必需,因为JS是HTML默认的脚本语言。
可以在HTML文档中放置任意数量的脚本。
脚本可以放在<head>
中,也可放在<body>
中。一般将脚本放在<body>
的最后,以改善显示速度,因为编译脚本会拖慢显示;也可统一放在<head>
中,以便方便管理、不会干扰页面内容。
脚本也可放在外部的JavaScript文件中,其后缀为.js
。通过在<script>
中设置src引用外部脚本。引用时可以使用完整的URL,也可用相对于当前网页的路径。
将脚本放在外部文件中有如下优点:
<script>
标签。HTML 输出流中使用 document.write,相当于添加在原有html代码中添加一串html代码。而如果在文档加载后使用(如使用函数),会覆盖整个文档。
JS是一种脚本语言,脚本语言是解释性语言的一种。在浏览器读取代码时,会逐行执行脚本,而不是在执行前对所有代码进行编译。
特点:
\
,可对字符串进行换行,以提高可读性(实际内容不会换行)。
document.write("Hello, \
World!")
注意只能对字符串使用。
很多特点与C++相同:
//
进行单行注释,//
后面的内容会被忽略;使用/*, */
进行多行注释,之间的内容会被忽略。{}
形成代码块。注:
<script>
内的开头与结尾(即包含所有JS代码)添加HTML的注释<!-- ... -->
。这样当浏览器不支持JS脚本时,不会执行其中的JS代码,会将其当做注释;而支持JS时,会执行JS代码。 //
可以避免JS执行-->
标签。
<script>
<!--
document.write("您的浏览器支持JS脚本!");
//-->
</script>
字面量(literal)是源代码中的固定值,如数字、字符串、表达式、确定的数组。可直接用来赋值(字面量叫做混合值,变量叫做变量值)。
与常量相比,常量是用变量表示的(只是不允许修改),而字面量是直接表示出来的,不用变量储存。变量是一个名称,字面量是一个值。
使用常量便于代码整体修改,使用字面量更直观。
除了常见的数字字面量、字符串字面量,还有:
表达式字面量,用于计算,如:1+2, 1*2
。
数组字面量(array)定义一个数组,如:[1, 2, 5]
。
对象字面量(object)定义一个对象,如:{name:"ABC", age:20, grade:"A"}
。
函数字面量(function)定义一个函数,如:function func(a, b) {return a*b;}
var
定义变量,使用,
可同时定义多个变量。定义变量但未对其赋值时,其值为undefined
;如果该变量以前被定义过,重新声明该变量不会改变其值(该声明会被忽略,当然如果此时赋值了值会改变)。$
和_
开头,但不推荐。变量名不能以数字开头。=
为变量赋值。/
为实数除法,没有整除。++, --
为运算后自增/自减,前缀++, --
为运算前自增/自减(同C)。x**y
为幂(相当于Math.pow(x,y)
)。+=, /=, <<=, <<<=, &=
等,但注意不推荐使用**=
。&&, ||, !
。但不同的是,非布尔型使用逻辑运算符时不是直接转换为布尔型,而是在判断时转换为布尔、返回结果时仍返回原类型,如0||3==3, 2||3==2, 0&&3==0, 2&&3==3
。variable = (condition) ? value1 : value2
。<<
为逻辑左移(填充0),>>
为算术右移(有符号右移,填充最高有效位),>>>
为逻辑右移(无符号右移,填充0)。当取模运算的被模数为负时,结果也为负(与模数无关)。
===
表示等值等型比较,即判定值相等且类型相等。!==
表示只不相等或类型不相等。
NaN
(与数字的任意比较结果都为false
)。加号:
+
可直接拼接字符串(此时+
称为级联运算符)。var x = 1 + 2 + "3"
的结果是"33"
(注意是从左到右运算,数字与数字相加是正常的加法!),var x = " " + 1
的结果是" 1"
(所有空格都会被保留,即使显示时可能被压缩)。而当数字和字符串(或两个数值字符串之间)相减/乘/除时,字符串会被转为数字!如:"5"-2
、5-"2"
、"5"-"2"
、"6"/"2"
都为3
。+
直接对变量使用时,可将其转为数字。如果变量不能转换为数值,则其值为NaN
。如+"5"==5, +"ABC"==NaN
。"null"
。"true"/"false"
。但注意字符串"true"/"false"
本身都是true。可包含值的类型(基本类型):数字(Number)、字符串(String)、布尔(Boolean)、bigint(可表示任意精度格式的整数)、Symbol(ES6中新的基本类型,表示独一无二的值,即字面量)。
不可包含值的类型(基本类型):空(null)、未定义(undefined)(两者均不含任何方法)。
引用数据类型:对象(Object)、数组(Array)、函数(Function)、日期(Date)。
基本类型也称原始数据、原始类型、基本数值、基本数据类型,指既非对象也无方法的数据。所有基本类型的值都是不可改变的。
数字(number)可用整数、小数、科学计数表示,不区分整数与实数,如:3.14, 123, 12e-5
。
字符串(string)用单引号、双引号表示都可。字符串中可以出现引号,只要不与包围字符串的引号相同(当然也可用转义引号)。
布尔(boolean)取值为true
或false
。
undefined表示该变量不含有值,null表示该变量不指向任何对象地址。
可为变量赋值undefined
或null
来清空变量,但更倾向于使用null
,因为null
会主动进行内存释放,如:var A=[1, 2, 3]; A=null;
会释放指向数组[1, 2, 3]
的引用(当对象不被任何变量引用时,会释放、回收)。
注意:undefined
和null
都表示"值的空缺",它们值相等,其布尔值都为false;undefined == null
会返回true,undefined === null
会返回false。
注意,对boolean值使用异或,其会变为int。
如[false] ^= true
的结果是1 而不是true。可以用x = !x
。
数组(array)用中括号包含,下标从0开始。
数组有三种声明方式:
1.var A = new Array()
或var A = []
定义大小为0的数组,通过A[x]=y
初始化A[x]
的内容,且会将数组大小扩展到x+1
,未被初始化的位置的值为undefined
。
2.var A = new Array(12, "qwq", 34)
,通过压缩数组(condensed array)。
3.var A = [12, "qwq", 34]
,通过字面量数组(literal array)。
字符串、对象、函数的具体内容见下。
使用typeof x
查看x
的数据类型(结果格式为string)(typeof
是一种运算符)。
对除null
以外的基本数据类型使用typeof
,会返回类型本身,如string, number, boolean, undefined
。
对于非基本类型(数组,对象,函数),typeof
的返回值要么是对象object
,要么是函数function
。此外,null
的数据类型也是object
(null
是一个特殊的对象值,含义是"非对象")。所以使用typeof
并不能区分一个变量是对象还是数组。
使用x instanceof obj
可判断x是否为obj类型。如:x instanceof Array
。用于判断准确类型。
使用相应方法也可判断x的准确类型。如:Array.isArray(x)
(在此之前可先判断Array.isArray
是否为true,可判断是否支持该方法)。
使用constructor
属性可返回某变量的构造函数,如:
(3.14).constructor // 返回函数 Number() { [native code] }
"John".constructor // 返回函数 String() { [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
属性可判断对象的准确类型(通过构造函数是否包含某字符串),如:
function isArray(A) {
return A.constructor.toString().indexOf("Array") > -1;
}
声明变量时,可使用new
为其指定类型,如:var x = new Number(), y = new Boolean(), z = new Object();
。但注意,new
声明的变量会被创建为对象(x,y
分别为Number对象、Boolean对象),应避免使用那些本可直接定义的类型(原始类型)的对象,如字符串、数值或布尔对象,它们会增加代码的复杂性并降低效率。
内容相同的字符串与字符串对象用===
比较会返回false。
原始类型和对象的区别(这不同于Python):
原始类型(如"abc")自身没有对象的属性和方法(如str.toUpperCase()),但效率更高;对象有自己的属性和方法,但效率更低。
但是,原始类型仍能使用相应对象的属性和方法,因为每种原始类型都可创建其“对象包装器”(包含String、Number、Boolean和Symbol),原始值在调用属性/方法时可执行如下操作:
1. 创建一个包含原始值字面量的对应类型的特殊对象,包含对应对象的所有属性和方法。
2. 执行创建出的特殊对象的被调用属性/方法。
3. 销毁特殊对象,返回到原始值。
所以,不能为原始类型添加属性/方法(赋值语句可以执行成功,但只是对特殊对象赋值,原始值仍不包含属性/方法)。
转String
String(x)
。
输出一个对象或变量时,会自动调用其toString
方法。
Number to String
使用String(x)
方法,或Number的方法x.toString()
。
Number的其它方法:
number.toExponential(x)
:将number的值转为科学计数法。返回String。
参数可选,规定科学计数法中的小数位数,范围为,默认会尽可能大。
number.toFixed(x)
:将number的值四舍五入为指定小数位数的数字。返回String。
参数可选,规定小数的位数,范围为,默认为0(即取整)。
number.toPrecision(x)
:将number转换为指定长度的数值字符串。
参数可选,规定要转换为几位数,范围为,默认为数字本身位数。
Boolean转String
使用String(x)
方法,或Boolean的方法x.toString()
。
如:false.toString()==String(false)=="false"
,true.toString()==String(true)=="true"
。
Date转String
使用String(x)
方法,或Date的方法x.toString()
。
转Number
Number(x)
,或用运算符+
。
当+
直接对变量使用时,可将其转为数字。如果变量不能转换为数值,则其值为NaN
。如+"5"==5, +"ABC"==NaN
。具体可见运算符部分。
特殊情况:
字符串(string)用单引号、双引号表示都可。字符串中可以出现引号,只要不与包围字符串的引号相同(当然也可用转义引号)。
字符串也是一种数组,可通过下标访问字符。
属性:
constructor
:返回创建字符串属性的函数。
length
:返回字符串的长度。
prototype
:允许向对象添加属性和方法。
方法:
https://www.runoob.com/js/js-strings.html
对象是拥有属性和方法的数据,是属性和方法的容器(即可存储多个值、函数)。
对象的键值对称为属性,方法是作为属性来存储的函数。
通过x.attr
或x["attr"]
访问属性或方法,通过x.func()
调用方法。
定义对象有四种方式:
1. 通过属性的"名称:值"对:var A = {name:"A", age:20, score:"A"}
。
也可分多行写:
var A = {
name: "A",
age: 20,
score: "A",
getScore: function() {
return this.score;
}
}
2. 先创建对象,再追加属性、方法。
var A = new Object();
A.name = "A";
A.age = 20;
A.getName = function() {return this.name;}
3. 将2.改为函数。
function InitA()
{
var obj = new Object();
obj.name = "A";
obj.age = 20;
obj.getName = function() {return this.name;}
return obj;
}
var A = InitA();
4. 将3.的函数直接改为对象。
function InitA()
{
this.name = "A";
this.age = 20;
this.getName = function() {return this.name;}
}
var A = new InitA;
注:定义时,同一变量名可被赋值多次(属性或方法),只以最后一次赋值为准。
使用function Function_Name(arguments)
定义函数。函数体放在大括号/花括号中。定义的函数可以在任意位置被调用。
形参称为parameters,实参称为arguments。调用Function_Name
获得的是函数对象(完整的函数声明代码),调用Function_Name()
获得的是函数结果。
函数可以返回任意类型的值或不返回值,没有确定的类型限制。
关于参数
传入的实参可以少于形参个数,若形参没有默认值,则为undefined。
传入的实参可以多于形参个数。
所有传入的实参都会被存到该函数对象的arguments
属性中。使用arguments[0], ..., arguments[arguments.length-1]
可访问所有实参。
arguments
类似数组,但没有Array的属性方法,只有length
属性和索引元素功能。
自调用函数
在表达式后面加()
,会得到自调用表达式,在此处会自动被调用。
可用此创建一个匿名自我调用的函数(没有函数名,注意函数要整体加括号)。
如:
(function () {
console.log('qwq');
})();
箭头函数
更简洁的函数表达式。类似Python的lambda
,但仍可加函数体。
语法:
(参数1, 参数2, ..., 参数n) => {函数体}
唯一参数 => {函数体} //当只有一个参数时,可省略小括号
() => {函数体} //没有参数时,保留一个小括号
(参数1, 参数2, ..., 参数n) => 表达式 //不使用大括号时,只能有一句表达式,表示返回值
(参数1, 参数2, ..., 参数n) => {return 表达式} //等同于上一行
作用域为可访问变量、对象、函数的集合。
全局作用域
在函数中声明的变量,为局部变量,处于全局作用域,只能在函数内部访问。
局部变量在函数执行时创建,在函数执行完成后销毁。
全局作用域
在函数外声明的变量,为全局变量,处于全局作用域,所有脚本和函数都可访问。
全局变量在页面关闭后销毁。
块级作用域
ESMAScript 6中新增了块级作用域。一对大括号内的部分,即为块作用域。
通过var定义的变量,没有块的概念,可以跨块访问、不能跨函数访问。
通过let定义的变量,不能跨块访问,当然也不能跨函数访问。
同一变量在同一作用域,只能使用一种方式声明。
如:
var a=1;
let c=0;
for(var i=1; i<4; ++i) {a=2; var b=3; let c=4;}
console.log(a, b); // 2 3
console.log(c); // 0
通过let,for, if
也可拥有自己的作用域(块级作用域),可用于定义循环变量等循环内用的变量,而不影响外部变量的值。
for
还有一个特点:定义循环变量的部分为父作用域,循环体内部是另一个子作用域,可以再次声明循环变量且互不干扰:
for(let i=0; i<3; ++i)
{
let i = 'abc';
console.log(i);// abc abc abc
}
此外var可以定义多次,let只能定义一次:
var a=1;
var a=2;
let b=1;
// let b=2; //Identifier 'b' has already been declared
console.log(a, b) // 2 1
HTML中默认的全局对象是页面本身,即window对象。所有全局变量(含函数)都属于window对象,为window的属性(或方法),既可直接用变量名访问,也可用window.name
访问。声明全局变量并赋值,会覆盖window
的该属性。
给未声明的变量赋值,该变量也将成为一个全局变量,也是window的一个属性。
不同的是,非严格模式下通过对未声明的变量赋值创建的全局变量,是全局对象的可配置属性,可以删除;而直接声明的全局变量,是不可配置全局属性,不可删除。
如:
var n1 = 1;
function f() {n2 = 2;}
f();
console.log(n1, window.n1); //1 1
console.log(n2, window.n2); //2 2
console.log(delete n1); //false 无法删除
console.log(n1); //1
console.log(delete n2); //true 可删除
console.log(n2); //ReferenceError: n2 is not defined.
HTML元素中可以使用JS添加事件属性:<element_name event_name="JS代码">
(使用单双引号都可)。
如:
通过点击按钮改变自身或其它元素(this
可换为getElementBy..
)的内容:
<button onclick="this.innerHTML=Date()">当前时间</button>
也可以在点击按钮时直接调用函数,且更常与函数一起使用:
<button onclick="DisplayDate()">当前时间</button>
DOM事件:https://www.runoob.com/jsref/dom-obj-event.html
为某元素添加监听事件:element.addEventListener(event, function, [useCapture])
(追加,同一事件可以同时执行多个函数)
为某元素删除监听事件:element.removeEventListener(event, function, [useCapture])
this
所指的对象,与其使用位置有关:
this
指该对象。this
指全局对象;但在严格模式下("use strict"
),this
未定义,是undefined(严格模式不允许默认绑定)。this
指全局对象。this
指接受事件的元素。在浏览器窗口中,全局对象即为[object Window]
,即window对象。
JS的if, if...else, if...else if...else
均与C相同。
JS的switch
也基本与C相同(包括break
,default
,case
内容不需要大括号)。
但注意,case
必须加break
,否则在匹配一个case后,会执行后面所有case的内容直到被break(匹配后,后面的case不会再被判定)。
JS还有switch
的类似写法:
const/var condition = ...;
let obj = {
'condition1' : () => { ... },
'condition2' : () => { ... },
'condition3' : () => { ... },
}
obj[condition]();
该写法类似函数的哈希表,但如果不存在obj[condition]
这一项,即没有对某个可能的condition
进行判断,会出错Uncaught TypeError: obj[condition] is not a function
,程序会终止运行。
for, while, do...while, break, continue
与C相同,包括只有一条语句时(如continue
)不需要大括号。如:
for (var i=0, len=A.length; i<len; i++)
document.write(A[i] + "<br>");
此外,还可以for in
,for of
:
for (var v of A):
console.log(v); //A[i]
for (const v of A): //可用const保证不修改元素
console.log(v);
for (let [k, v] of mp) //迭代一个map
console.log('map:', k, v);
可用label_name:
对一个代码块进行标记。用break label_name
可从当前代码块中直接跳出。
直接使用break
时,默认从当前循环/switch代码块中跳出。使用break label_name
可以从任意一个代码块中跳出。
如:
Output:
{
document.write(A[0] + '<br>');
document.write(A[1] + '<br>');
break Output; //跳出
document.write(A[2] + '<br>');
}
OuterLoop: //直接跳出外部循环
for(let i=0; i<5; ++i)
{
InnerLoop:
for(let j=0; j<5; ++j)
{
if(i<=2) break;
else if(i==3) break OuterLoop;
}
}
innerHTML
innerHTML
属性中。 innerHTML
属性进行更改,或用其获取元素内容。例:
通过DOM中定义的document.getElementById(x)
获取id为x的HTML元素,然后用其innerHTML
属性修改内容(同样还有document.getElementByName(x)
获取name为x的HTML元素,但返回的是一个数组)。
<p id="para1">emmm</p>
<script>
document.getElementById("para1").innerHTML = "段落已被更改。";
</script>
document.write()
document.write()
相当于直接在原HTML代码中添加参数中的内容。参数可以是字符串或HTML代码,但要加引号;可以是数字、返回文本的函数等,不需要引号。 例:
<script>document.write("<h1>这是标题</h1>")</script>
会在相应位置生产一个一级标题。
注意:
如果在文档加载完成后,再执行document.write()
,输出内容会将整个HTML页面覆盖。
因为如果执行document.write()
前没有调用document.open()
(比如页面加载完成后执行),会先调用document.open()
,导致清空当前文档内容。
window.alert()
window.alert()
会弹出警告框来显示数据。参数可以是字符串(要加括号)、数字、返回文本的函数等,但不能是HTML代码。
console.log()
console.log()
可在浏览器控制台中输出内容。在调试模式的控制台(console)中查看输出的内容。
内容可以用格式化字符串输出。
例:
<script> console.log(Date()); </script>
类似Python的try...except
。检测到错误后可对错误进行处理,且不会终止程序。
用try
定义进行错误检测的代码块;catch
定义错误处理代码块。注意该代码块似乎必须要加大括号。
例:
try {
qwqalert('qwq');
}
catch(e) {
alert('Error:\n' + e.message + '\n' + '点击以继续\n');
}
finally {
console.log('Finish') //Finish
}
可加入finally
,同Python,不论是否捕捉到错误,最后都会执行finally
代码块。
类似Python的raise
。使用throw exception
可主动抛出任意类型的错误。
exception
可是任意类型(字符串、数字、对象等),使用catch
捕捉到后可输出该对象。
例:
var x = document.getElementById("qwq").value;
try {
if(x=="") throw "值为空";
else if(isNaN(x)) throw "非法值";
else if(x<10) throw x;
}
catch(e) {
console.log( "Error: " + e );
}
使用console.log
进行输出。
使用debugger
语句可设置一个断点,程序会在该处停止执行,直到手动继续。
例:
console.log("stop");
debugger;
console.log("continue");
使用"use strict"
进入严格模式,指定代码在严格条件下进行。
"use strict"
不算一条语句,属于一个字符串字面量,所以即使不支持严格模式也会被忽略。
"use strict"
只允许出现在整个脚本或函数体的开头(在函数中使用则只对该函数生效)。
使用严格模式可以:
1. 消除代码运行的一些不安全之处,保证代码运行的安全。
2. 提高编译器效率,增加运行速度。
3. 符合规范,更严谨。
严格模式的限制:
delete obj
)。delete func
)。eval()
中创建的变量不能被eval
之外调用(eval("var x=2")
后x
依旧未声明)。with()...
?)。this
值为undefined。声明提升
变量提升、函数提升(hoisting):JS中,所有变量和函数的声明会被放到最顶部。所以,变量和函数可以先使用后声明。
即使如此,也应先声明后使用。严格模式下不允许使用未先声明的变量和函数。
注意只有声明部分会被提升,初始化的赋值部分不会被一起提升。
如下例输出1 undefined
:
var x=1;
console.log(x, y);
var y=2;
正则表达式是由一个字符序列形成的搜索模式。
语法:/正则表达式主体/可选修饰符
。
JS中,正则表达式常用于字符串的两个方法:search(), replace()
。
search(x):参数可以为字符串或正则表达式。查找字符串中与串相等(或与正则表达式相匹配)的第一个子串,并返回那个子串的起始位置。
replace(x, y):第一个参数可以为字符串或正则表达式,第二个参数为字符串。将字符串中与相等(或与正则表达式相匹配)的所有子串,替换为字符串。
https://www.runoob.com/regexp/regexp-syntax.html
i
:匹配时对大小写不敏感。
g
:进行全局匹配(查找所有匹配,在找到第一个匹配后不停止)
m
:进行多行匹配。
JS中,RegExp对象是一个预定义了属性和方法的正则表达式对象。
具体可见:https://www.runoob.com/jsref/jsref-obj-regexp.html。以下是常用的正则表达式方法。
test()
判断一个字符串是否匹配某个模式,返回true或false。
例:
var s=/e/;
console.log( s.test("abcde") ) //true
console.log( /e/.test("abcde") ) //true
exec()
查找给定串中与正则表达式匹配的结果,返回一个存放了结果的数组。
如:
console.log(/e/.exec("The best things in life are free!")); //e
array.filter(function(value, index, arr), thisValue);
函数常用箭头函数表示,index, arr
是可选的。
返回一个包含所有满足条件的元素的数组。
滚动页面
https://blog.csdn.net/weixin_38990605/article/details/124980964
滚动至页面最底端:
无滚动条:
var height = document.body.clientHeight;
window.scroll({ top: height , left: 0, behavior: 'smooth'})
有滚动条:
var height = document.body.scrollHeight;
window.scroll({ top: height , left: 0, behavior: 'smooth'})
scrollHeight、clientHeight、offsetHeight具体的范围:
回到顶部:
window.scroll({ top: 0 , left: 0, behavior: 'smooth'})
去某一元素处:
let btn = document.getElementById('btn');
let height = btn.offsetTop ;
window.scroll({ top: height , left: 0, behavior: 'smooth'})
另附查资料看到一个父组件滚动法:
let item = document.getElementById("item"); // 指定的元素
let wrapper = document.getElementById("wrapper"); // 其父元素必须是产生滚动条的元素
wrapper.scrollTo(item.offsetLeft, 0); // 横向
wrapper.scrollTo(0 , item.offsetTop); // 竖向