变量
var
var
声明全局或函数级别作用域的变量
1 2 3 4 5 6 7 8 9 10
| var a; var b = "123"; var c = 0, d = 1;
var li = [1,2,3,4]; var [n1,n2,n3,n4,n5] = li; console.log(n1,n2,n3,n4,n5)
>>> 1 2 3 4 undefined
|
let
let
声明块级别作用域的变量
在块级作用域中申明的变量,在外不能访问到
1 2 3 4 5 6
| { let a = 123; } console.log(a)
>>> Uncaught ReferenceError: f is not defined
|
相同作用域下不能用let
重置
1 2 3 4
| let a = 1; let a = 2;
>>> Uncaught SyntaxError: Identifier 'a' has already been declared
|
const
const
在块级作用域声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改,与let
一样不能重置变量
1 2
| const a = 666; const a = 777;
|
但其实const
申明的对象可以被修改
1 2 3 4
| const a = [1,2,3] a[0] = 0; console.log(a) >>> [0,2,3]
|
变量提升
函数和变量的声明都将被提升到函数的最前面
1 2 3
| a = 0; console.log(a); var a;
|
函数申明形式创建的函数,在执行前会被创建
函数表达式不会被提前
1 2 3 4 5 6 7 8 9 10 11
| fun(); function fun(){ console.log(666); } >>> 666
fun2(); var fun2 = function(){ console.log(777); } >>>Uncaught TypeError: fun2 is not a function
|
数据类型
typeof
用于检查类型
String
Number
1 2 3 4
| console.log(Number.MAX_VALUE) >>> 1.7976931348623157e+308 console.log(Number.MIN_VALUE) 5e-324
|
Infinity
正无穷
-Infinity
负无穷
NaN
not a number
浮点型运算结果可能不精确
Boolean
Null
null
空对象
Undefined
undefine 未定义
Object
类型转换
1 2 3 4 5 6
| var a = 123; a = a.toString();
a = String(a);
a = a + "";
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var a = "123"; a = Number(a);
var b = "12abc"; b = Number(b);
var c = null; c = Number(c);
var a = "100px" var b = parseInt(a)
var a = "0.5em" var b = parseFloat(b)
|
0
、NaN
、""
、null
、undefined
被转为false
1 2 3
| var a = 0; a = Boolean(a); a = !!a
|
其他
16进制 : 0x10
8进制: 010 , 有些浏览器当做10进制
2进制:0b10 ,兼容性差
Unicode: \u100 (网页中使用⚀)
运算符
算术运算符
+
-
*
/
%
一元运算符
-a
+a
自增自减
a++
原值 ,++a
新值
逻辑运算符
!
非
&&
与
||
或
赋值运算符
a += 1;
……
关系运算符
比较字符串数字一定要转型
相等运算符
==
===
条件运算符
条件表达式?语句1:语句2;
true执行1,false执行2
运算符优先级
…
循环判断
if
1 2 3 4 5
| if(){ ...; }else if(){ ...; }
|
switch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| if(a == 1){ ...; }else if(a == 2){ ...; }
switch(a == 1){ case 1: ...; case 2: ...; default: ...; break; }
|
while
1 2 3 4 5 6 7 8
| while(){ }
while(true){ }
|
for
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for(var a=1; a<10; a++){ ...; }
for(;;){ }
name_test: for(;;){ break name_test; }
|
对象 Object
内建对象
ES标准定义的对象
function
Math
String
…….
宿主对象
浏览器提供的对象
BOM、DOM里的对象
window
常用属性
document
文档对象
console
location
地址对象,读取网页链接或控制跳转
localStorage
本地储存
screen
获取屏幕分辨率
scrollX、scrollY
X、Y滚动条位置
常用方法
alert
confirm
blur
将焦点移出当前窗口
close
关闭窗口
eval
执行字符串形式的js语句
focus
激活当前窗口
open
打开新窗口(标签页)
openDialog
打开新对话框窗口
print
显示打印功能的对话框
prompt
弹出输入框(会阻塞js)
scroll
控制滚动条到指定位置
stop
停止加载
自定义对象
1 2 3 4 5 6 7 8 9 10 11
| var obj = new Object(); obj.name = "小庄"; console.log(obj.name);
delete obj.name;
obj["123"] = 456; console.log(obj["123"]);
console.log("age" in obj);
|
1 2 3 4 5 6 7 8
|
var a = {}; var b = { name:"小庄", age:19, skills:{shoot:100;} };
|
函数
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var fun = new Function("console.log('6666')")
function func_name(a,b){ return a+b; }
var fun1 = function(){ ...; }
(function(){ return; })()
|
方法
1 2 3 4 5 6 7 8 9 10 11
| var fun = function(){ return; } fun()
var b = { say:function(){ alert("hi"); } } b.()
|
作用域
全局作用域
在js中直接写的代码,页面打开时创建,关闭时销毁;
在全局作用域中有一个对象window
,创建的变量都会作为window
的属性保存;创建的函数作为window
的方法保存;
全局作用域中的变量都是全局变量
1 2 3 4 5 6 7 8
| var a = 123; function fun(){ console.log("6"); } console.log(window.a) window.fun() >>> 123 >>> 6
|
函数作用域
函数调用时创建,执行完毕销毁,每调一次创建一个,互相独立;
全局作用域中无法访问其中的变量;
在函数作用域中操作一个变量时,先在自身作用域找,没有就找上一级,直到全局作用域,如果没找到就ReferenceError
隐含参数
this
解析器在调用函数时向内部传递的一个隐含参数,this
根据函数调用方法的不同指向不同对象;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function fun(){ console.log(this); }
var obj={ name:"小庄", say:fun }; fun(); obj.say()
>>>Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>>>{name: '小庄', say: ƒ}
|
call() 和 apply()
call()
和apply()
都是函数对象的方法,调用时都会执行函数
调用时,可以将一个对象指定为第一个参数,此时对象会成为函数执行时的this
1 2 3 4 5 6
| var a = {name:"杏花"}; function fun(){ console.log(this.name); } fun.call(a); >>> 杏花
|
call()
和apply()
传参方式不同
1 2 3 4 5 6 7 8 9 10
| function fun(a,b){ console.log(this.name+a+","+b); } obj = {name:"杏花"};
fun.call(obj,1,2); fun.apply(obj,[1,2])
>>> 杏花1,2 >>> 杏花1,2
|
arguments
同样是被传入的隐含参数,是一个类数组对象
- 调用函数传递的实参都会储存在
arguments
中,arguments.length
可以用来获取实参的长度
- 即使不定义形参,也能用它取到
1 2 3 4 5
| function fun(){ console.log(arguments[0]); } fun("haha",123); >>> haha
|
arguments
有一个callee
属性,就是当前正在执行的函数
1 2 3 4 5 6 7 8
| function fun(){ console.log(arguments.callee); } fun("haha",123);
>>>ƒ fun(){ console.log(arguments.callee); }
|
工厂函数
1 2 3 4 5 6 7
| function createSth(name){ var obj = new Object(); obj.name = name; return obj; }
var o = createSth("小庄");
|
构造函数
构造函数通过new
关键字创建
会立刻创建一个新的对象
将新建对象设为函数中的this
执行代码
返回对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function Preson(name){ this.name = "丁" console.log(this.name) } var p = new Person();
function Plants(name){ this.name = "plant"; console.log(this.name) } var p2 = new Plants();
console.log(p2 instanceof Person); >>> false
|
看下面这段代码
1 2 3 4 5 6 7 8 9 10
| function Person(name){ this.name = name; this.run = function(){ console.log(this.name+"润了"); } } var p1 = Perso("a"); var p2 = Person("b"); console.log(p1.run == p2.run) >>> false
|
如果使用该构造函数构造n个对象,就会创建n个新run
方法,这是没必要的:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function Person(name){ this.name = name; this.run = run; } function() run(){ console.log(this.name+"润了"); }
var p1 = Perso("a"); var p2 = Person("b"); console.log(p1.run == p2.run) >>> true
|
但是上方这种将函数定义在全局作用域中,会污染全局作用的的命名空间,也不安全,这就要说到原型对象
原型对象 prototype
创建的每个函数,解析器都会向其中添加prototype
属性,通过__proto__
访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function MyClass(){ } MyClass.prototype.a = 123;
var mc = new MyClass(); var mc2 = new MyClass(); var mc3 = new MyClass();
console.log(mc.a) >>> 123
console.log(a in mc)
console.log(mc.hasOwnProperty("a"))
|
Object对象的原型没有原型
toString()
console.log()
打印对象时,实际上就是输出了对象的toString()
的返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function P(){ this.name = "A" } var a =new P();
console.log(a); console.log(a.toString());
p.prototype.toString = function(){ console.log("666"); }
console.log(a); console.log(a.toString());
|
垃圾回收
当一个对象没有任何变量或属性对它引用,此时永远无法操作它,它就是个垃圾;
JS有自动的垃圾回收机制,会自动将其销毁,我们只需将其引用设为null
数组 Array
1 2 3 4 5 6 7
| var arr = new Array(); var arr1 = new Array(3); var arr2 = []; arr[0]=1; console.log(arr1.length) arr2.length = 4 console.log(arr2.length)
|
方法 JavaScript 数组参考手册 (w3school.com.cn)
时间 Date
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var d = new Date(); console.log(d);
>>> Wed Aug 17 2022 06:26:05 GMT+0800 (中国标准时间)
var d2 = new Date("08/08/2021 12:00:30");
var d3 = d2.getDate();
var day = d2.getDay();
var month = d2.getMonth();
var year = d2.getFullYear(); ...
var time = d2.getTime();
|
JavaScript Date 参考手册 (w3school.com.cn)
Math
它不是一个构造函数,属于一个工具类,无需创建
1 2
| console.log(Math.PI); >>> 3.141592653589793
|
JavaScript Math 参考手册 (w3school.com.cn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| console.log(Math.ceil(1.4)); >>> 2
console.log(Math.floor(1.4)); >>> 1
console.log(Math.round(1.4)) >>> 1
console.log(Math.random());
var x = 10; console.log(Math.round(Math.random()*x)); >>> 8
console.log(Math.round(Math.random()*(y-x))+x);
|
包装类
JS中提供了三个包装类,通过其可将基本数据类型转为对象:
- String()
- Number()
- Boolean()
1 2 3 4 5 6
| var num = new Number(1); console.log(typeof num); >>> object
var num2 = new Number(1); console.log(num == num2);
|
开发中基本不用包装类
当对基本数据类型的值调用属性和方法时,浏览器会临时使用包装类将其转换为对象,再调用属性和方法
调用完后再转换为基本数据类型
1 2 3 4
| var a =132; a = a.toString(); console.log(a); >>> 123
|
字符串 String
一些方法
在底层字符串以数组形式保存 [“H”, “e”, …….]
JavaScript String 参考手册 (w3school.com.cn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var str = "Hello YZYYZ"; console.log(str.length); >>> 11
var a = str.charAt(0);
var a = str.charCodeAt(0);
var a = String.formCharCOde(72);
var str.concat("哈哈");
var a = str.indexOf("H");
lastIndexOf()
var a = str.slice(0,5);
var a = str.subString(1);
var a = str.split(" ")
var a = str.toUperCase() var a = str.toLowerCase()
|
正则表达式
1 2 3 4 5 6 7
| var re = new RegExp("a"); var str = 'abc'; console.log(re.test(tel));
var re = /^1[3-9]\d{9}$/; var tel = "13009985544"; console.log(re.test(tel))
|
支持正则的String对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var str = "123qqq345www456eee567ABCDEFG"; var re = /[a-z]+/ig;
var result = str.search(re); console.log(result); >>> 3
result = str.match(re); console.log(result); >>> ['qqq', 'www', 'eee', 'ABCDEFG']
result = str.replace(re,"*"); console.log(result); >>> 123*345*456*567* result = str.split(re); console.log(result); >>> ['123', '345', '456', '567', '']
|
DOM
Document Object Model 文档对象模型
JS通过DOM对HTML文档进行操作
- 文档:HTML 网页
- 对象:网页的每个部分转为一个对象
- 模型:表示对象间的关系
节点 Node
节点是构成网页的最基本组成部分,网页中每部分都可称为一个节点
|
nodeName |
nodeType |
nodeValue |
文档节点 |
#document |
9 |
null |
元素节点 |
标签名 |
1 |
null |
属性节点 |
属性名 |
2 |
属性值 |
文本节点 |
#text |
3 |
文本内容 |
浏览器提供 文档节点 对象,其是window
属性,可以在页面直接使用
1 2 3 4 5 6
| ... <button id="btn">点我</button> <script type="text/javascript"> console.log(document.getElementById("btn").innerHTML) </script> ...
|
事件
HTML DOM 事件 (w3school.com.cn)
- addEventListener 添加事件监听器
- dispatchEvent 手动触发指定事件
- getAttribute 获取标签的指定属性
1 2 3 4 5
| function fun(){ alert("haha"); } var btn = document.getElementById("btn"); btn.onclick = fun
|
文档的加载
1 2 3 4 5 6 7 8 9 10 11 12 13
| ...
<script type="text/javascript"> window.onload(){ btn = document.getElementById("btn"); btn.onclick = function(){ alert(btn.innerHTML) } } </script>
<button id="btn">点我</button> ...
|
DOM查询
获取元素节点
- getElementById()
- getElementsByTagName()
- getElementsByName()
获取子节点
childNodes
文本属性也会当做节点
children
推荐
firstChild
firstElementChild
第一个子元素 虽然IE已死,但是它只兼容IE9+
lastChild
获取父节点和兄弟节点
parentNode
父节点
previousSibling
前一个兄弟节点
nextSibling
根据class
getElementsByClassName
包括自身的所有元素
选择器
DOM增删改
HTML DOM Element 对象 (w3school.com.cn)
document.createElement()
需要一个标签名作为参数,并返回这个对象
document.createTextNode()
创建文本节点,参数为文本,并返回节点
appendChild()
父元素 . appendChild(子元素)
insertBefore()
父节点 . insertBefore(新节点,旧节点)
repleaceChild()
repleaceChild(新节点,旧节点)
removeChild()
父节点 . removeChild(子节点)
父节点:子节点 . parentNode
样式操作
操作内联样式
obj.style.xxx = “xxx”
obj.style[“xxx”] = “xxx”
查询样式
getComputedStyle(obj,null)
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
| <script type="text/javascript"> window.onload = function(){
const body = document.getElementsByTagName("body")[0]; body.onpagehide = function(){ localStorage.removeItem("created"); }; const btn = document.getElementById("change-dom"); const code0 = document.getElementById("code0"); const block = document.getElementsByTagName("blockquote")[0]; const block2 = document.createElement("blockquote"); const after_btn = btn.parentNode;
btn.onclick = function(){ console.log(localStorage["created"]); if (localStorage["created"]==="0" || localStorage["created"] ===undefined){ btn.innerHTML = "点击收起"; code0.style.visibility = ""; block2.innerHTML = "你正在查看的是废弃的文章"; block2.style.background = "#f4433678"; block2.style.color = "#fff"; block2.style["border-left"] = "4px solid #f44336"; after_btn.appendChild(block2); localStorage.setItem("created","1"); } else if(localStorage["created"]==="1"){ after_btn.removeChild(document.querySelector("#post > section.article.typo > div.article-entry > div.button.readmore > blockquote")); code0.style.visibility = "collapse"; btn.innerHTML = "点击查看"; localStorage["created"]="0"; } } }
</script>
|