JavaScript
网页统分为三大部分:结构(HTML)、表现(CSS)和行为(JavaScript)。
JavaScript
JavaScript简介
JavaScript是解释型语言,有着类似C和Java的语法结构,动态语言,基于原型的面向对象。
一个完整的JavaScript实现应该由以下三个部分构成:ECMAScript、DOM、BOM。
代码的位置
在HTML中,JS代码可以编写在<script>
中。
1 | <script type="text/javascript"> |
可以内联到<button>
标签的onclick
属性中。
1 | <button onclick="alert('Hello world!');">点我!</button> |
可以内联到<a>
标签的href
属性中。
1 | <a href="javascript:alert('Hello world!');">点我!</a> |
可以使用专门的js文件,然后引入。此时<script>
标签内部的代码被忽略。
1 | <script src="./demo.js"></script> |
输出
弹出警告框。
1 | alert(); |
弹出带有文本框的提示框,函数返回用户输入的字符串。
1 | var input = prompt("请输入密码"); |
带有消息和确认取消按钮的提示框。
1 | var flag = confirm("确认提交?"); |
文档输出,向<body>
中写入内容。
1 | document.write(); |
控制台输出。
1 | console.log(); |
JavaScript基本语法
字面量和变量
字面量都是不可改变的值,如1
,2
,"Hello"
。
变量可以用来保存值。
1 | var hello = "Hello world!"; |
标识符由字母、数字、下划线、美元符组成;不能以数字开头;不能是关键字或保留字;一般使用小驼峰规则。变量名可以使用中文,但不要使用。
数据类型
数据类型指的是字面量的类型。
- String 字符串
- Number 数值
- Boolean 布尔值
- Null 空值
- Undefined 未定义
- Object 对象
Object是引用数据类型。
typeof
用于查看类型。
字符串使用双引号或单引号,不能嵌套,可以使用\
转义。Unicode使用\u
转义。
所有数值,包括整数和浮点数都使用Number。
Number型的最大值Number.MAX_VALUE
约为$1.79769\times 10^{308}$,超过后认为Infinity
;最小值Number.MIN_VALUE
约为$5\times10^{-324}$。
NaN
表示不是数字,如字符串乘字符串。
十六进制以0x
开头,八进制以0
开头,二进制以0b
开头(兼容性不好)。
布尔值只有true
和false
。
Undefined
类型值只有undefined
,表示未定义的变量。
Null
类型值只有null
,专门用来表示为空的对象,类型为Object
。
类型转换
- 转换为String:
.toString()
方法,不能转换null
和undefined
。String()
函数,底层实现是检测和调用.toString()
方法。+""
加空串会转换为字符串。
- 转换为Number:
Number()
函数- 若不能转换给出
NaN
。 undefined
转换为NaN
。- 空串
""
或空白串" "
,"\t"
转换为0
。 true
转换为1
,false
转换为0
。null
转换为0
。
- 若不能转换给出
parseInt()
和parseFloat()
转换字符串- 将有效字符串转换为Number,遇到非数字停止。
parseFloat()
可以转换科学计数法。- 非有效返回
NaN
。 - 其他数据类型先转换为String再转换,所以给出
NaN
。 070
这种字符串可能转换错误,可以使用parseInt("070",10)
表示以十进制转换。
-0
,*1
,/1
除了加号以外的算术运算符.+
正号
- 转换为Boolean
Boolean()
函数0
和NaN
为false
,其余都为true
。- 空串
""
为false
,其余都为true
。 null
和undefined
为false
,其余对象为true
。!!
运算符
typeof
是运算符,可以获取数据类型,返回字符串。+
,-
,*
,/
,%
- 除了字符串拼接,非Number类型值会先转换为Number。
- 任何值和
NaN
运算都是NaN
。 - 两个字符串相加视为拼接。
- 任何值和字符串相加视为字符串拼接。
+
正号,-
负号- 对于非Number,先转换为Number。
++
自增,--
自减- 无论是前置
++
和后置++
,都会让变量立即自增,但返回的值不同。
- 无论是前置
&&
与,||
或,!
非- 与和或均为短路运算。
- 非
Boolean
会先转换为Boolean
,但会返回短路时的原值:与运算如果第一个值为true
返回第二个值,如果第一个值为false
返回第一个值;或运算如果第一个值为false
返回第二个值,如果第一个值为true
返回第二个值。
=
赋值,+=
,-=
,*=
,/=
,%=
>
,<
,>=
,<=
- 除了字符串比较,非数值会先转换为数值。
- 任何值和
NaN
比较总会得到false
。 - 两个字符串比较会进行字符串比较,使用Unicode。
==
,!=
- 一般来讲会转换为Number进行相等比较。
null == 0 // false
undefined
衍生自null
,undefined == null //true
NaN
的相等比较总会给出false
。可以通过isNaN()
判断是否为NaN
。!=
取值为==
取反。
===
全等,!==
不全等- 全等和不全等不会做类型转换。
?:
条件运算符,
逗号运算符
运算符优先级
.
,[]
,new
()
++
,--
!
,~
,+
,-
,typeof
,void
,delete
%
,*
,/
+
,-
<<
,>>
,>>>
<
,<=
,>
,>=
==
,!=
,===
&
|
&&
||
?:
=
,+=
,-=
,*=
,/=
,%=
,<<=
,>>=
,>>>=
,&=
,^=
,|=
,
语句
1 | if(exp){ |
面向对象
- 内建对象由ES标准定义,如Math,String,Number,Boolean,Function,Object等。
- 宿主对象由JS的运行环境提供,如BOM,DOM等。console和document就是宿主对象。
- 自建对象由开发人员创建。
对象基本操作
对象通过new
创建,对象属性用.
创建,用delete
删除。
1 | var obj = new Object();//创建对象 |
对象的属性的本质是键值对,键为字符串,可以用[]
控制。
1 | //属性名可以用任意字符串,但特殊的字符串需要使用[],此时甚至可以传入变量 |
可以通过in运算符检查对象是否拥有指定的属性。
1 | if("age" in obj){ } |
可以使用foreach
来枚举对象的全部属性。
1 | for(var n in obj){ |
对象是引用数据类型,==
比较的是是否为同一对象。
当直接打印对象时,使用对象的toString()
方法,定义在Object的原型之中,可以重写这个方法。
对象字面量
{}
为对象字面量,可以在创建对象的同时添加属性,属性名可以加引号。
1 | var obj = {}; |
函数对象
函数也是对象,具有普通对象的功能,函数中可以封装代码,在需要时执行功能。
可以在构造函数时将代码以字符串的形式传递给构造函数。
1 | var fun = new Function("console.log('Hello world');"); |
一般使用函数声明来创建函数。
1 | function fun(){ |
也可以使用函数表达式创建函数。
1 | var fun = function(){ |
可以在函数中使用参数。调用时多余参数会被忽略,不足的参数为undefined
。
1 | function sum(x,y){ |
可以立即执行声明的匿名函数。
1 | (function(){ alert("Hello world!";) })(); |
对象的属性也可以是函数,此时称为方法。
函数在调用时会传递this
,即调用函数的对象还会传递arguments
,即传递的参数,argument
是一个伪数组。
arguments
有一个属性callee
,对应调用的函数。
对函数对象调用call()
和apply()
会调用函数,传入的参数将会作为this
,但apply()
要求将参数封装为数组。
1 | func.call(obj, arg...);//obj.func(arg...); |
作用域
JS中的作用域分为全局作用域和函数作用域。
全局作用域:
- 编写在
<script>
中的变量拥有全局作用域,在页面打开时创建,在页面关闭时销毁。 - 在全局作用域中有一个全局对象
window
,代表浏览器的窗口。全局作用域中的所有变量都作为window
的属性储存,所有函数都作为window
的方法储存。 var
关键字声明的变量,会在所有的代码执行之前被声明。- 使用
function
声明的函数,会在所有的代码执行之前被声明及定义。
函数作用域
- 调用函数时创建函数作用域,函数执行完毕后作用域销毁。
- 函数作用域中可以访问全局作用域。
- 函数作用域中的重名变量就近使用。
var
关键字声明的变量,会在函数中所有的代码执行之前被声明。- 定义的形参相当于在函数作用域中定义的变量。
- 不用
var
关键字声明的变量,都会是全局变量。 - 使用
function
声明的函数,会在函数中所有的代码执行之前被声明及定义。
闭包
为了让函数外部可以访问函数作用域的变量,可以使用闭包。
1 | fuction f(){ |
构造函数
使用工厂方法来统一创建对象
1 | function createObj(name, age){ |
可以声明构造函数。调用构造函数时会立刻创建新的对象,将新建的对象设置为函数中的this
,执行函数中的代码,并把对象作为返回值返回。使用同一个构造函数创建的对象称为同一类对象,将构造函数称为一个类。
1 | function Person(name, age){ |
instanceof
运算符检查一个对象是否是一个类的实例。
1 | var steve = new Person("steve", 11); |
原型对象
每创建一个函数,解析器都会向函数添加一个属性prototype,这个属性对应着一个对象,称为原型对象。
如果函数作为普通函数调用,原型对象不起作用。当函数作为构造函数调用,他所创建的对象都有一个隐含属性指向原型对象,可以通过__proto__
访问。
原型对象相当于公共区域,可以将对象所共有的内容统一设置到原型对象中,如类方法。当访问对象的属性或方法时,如果没有在自身范围内找到,则会在原型对象中寻找。
原型对象也是对象,原型对象也有原型对象,直到Object的原型对象。Object对象的原型对象没有原型对象,对应null。
1 | Person.prototype.sayName = function(){ |
使用in
检查属性时,也会包括原型对象。可以使用hasOwnProperty()
检查对象自身是否拥有该属性。
JSON
Javascript Object Notation用字符串表示一个对象。对象用{}
表示,数组用[]
表示。
JSON工具类用于转换JSON。(IE8+)
1 | var obj = JSON.parse(json); |
IE7解决案:
1 | var obj = eval("(" + str + ")"); |
不过还是引入一个JSON库比较好。
内建对象
Array
数组也是对象。使用数字索引作为属性名存储元素。数组的存储性能要比普通对象要好。typeof
检查数组对象会给出object。
1 | var arr = new Array();//创建数组 |
数组方法
1 | arr.push(obj);//向数组末尾添加一个或多个元素,返回长度 |
数组遍历使用forEach()
,需要传入回调函数,回调函数的三个参数分别代表当前元素、索引和数组。IE8及以下不支持。
1 | arr.forEach(function(value, index, array){ |
Date
1 | var d = new Date();//默认当前时间 |
Math
Math
不是构造函数,不用创建对象,是一个工具类。属性为数学常量,方法为数学函数。
1 | Math.PI; |
包装类
可以将基本数据类型包装为对象,开发中不常用。浏览器会临时使用包装类处理基本数据类型调用的方法。
1 | var str = new String("Hello wrold!"); |
String
String类的底层实现是字符数组。
1 | var str = "Hello world"; |
正则表达式
匹配模式包括"i"
和"g"
,指忽略大小写和全局匹配模式,可以多个匹配。
1 | var r = new RegExp("正则表达式","匹配模式"); |
基本语法
/a/
含有a/ab/
含有ab/a|b/
含有a或b/[ab]/
含有a或b/[a-z]/
含有小写字母/[A-z]/
含有任意字母/[0-9]/
含有任意数字/a[bcd]z/
含有abz或acz或adz/[^0-9]/
含有非数字的字符
量词
/a{3}/
含有aaa/ab{3}/
含有abbb/(ab){3}/
含有ababab/a{1,3}/
含有a或aa或aaa/a{3,}/
含有aaa或aaaa或aaaaa…/ab+c/
含有abc或abbc或abbbc…/ab*c/
含有ac或abc或abbc或abbbc…/ab?c/
含有ac或abc
开头结尾
/^a/
以a开头/a$/
以a结尾/^a$/
只匹配a
元字符
.
除了换行和结束的任意字符\.
匹配”.”\w
任意字母、数字、下划线\W
非字母、数字、下划线\d
任意数字\D
非数字\s
空格\S
非空格\b
单词边界,如\bchild\b
查找单词child\B
非单词边界
例子
1 | var phoneReg = /^1[3-9][0-9]{9}$/; |
支持正则表达式的String类方法
1 | str.split(reg);//以正则表达式拆分字符串,默认全局匹配拆分 |
DOM
文档对象模型,文档指整个网页,网页中的所有元素都转换为对象。
节点
常用节点:
- 文档节点:整个HTML文档
- 元素节点:HTML标签
- 属性节点:元素属性
- 文本节点:标签中的文本内容
nodeName | nodeType | nodeValue | |
---|---|---|---|
文档节点 | #document | 9 | null |
元素节点 | 标签名 | 1 | null |
属性节点 | 属性名 | 2 | 属性值 |
文本节点 | #text | 3 | 文本内容 |
对象
1 | <button id="btn" class="butn">我是一个按钮</button> |
元素的属性可以直接用对象的属性获取,除了class
需要使用className
。
innerHTML
获取内部HTML代码innerText
获取内部文本
事件
响应函数
可以在HTML标签中使用事件。
1 | <button id="btn" onclick="alert('Ouch!');">我是一个按钮</button> |
应该在JS中处理事件,这时调用的回调函数称为响应函数。
1 | var btn = document.getElementById("btn"); |
响应函数需要在对象加载后再绑定,否则无法获取到对象。
冒泡
当后代的事件触发时,祖先的元素相同事件会依次触发,称为冒泡。可以用event.cancelBubble = true
取消冒泡。
将事件绑定给元素的共同的祖先,这样当后代元素上的事件触发时会一直冒泡到祖先,称为事件的委派。
事件触发时,如果事件由内向外触发,称为事件冒泡,而事件从外向内的过程是捕获阶段。默认在捕获阶段不会触发事件,捕获结束后才开始触发冒泡。可以设置在捕获阶段就触发。
绑定响应函数
addEventListener()
也可以绑定响应函数(IE9+)。事件以字符串传入,不需要”on”。第三个参数表示是否在捕获阶段触发事件。可以绑定多个事件,先绑定者先执行。IE8使用attachEvent()
,后绑定者先执行,且函数中的this表示window。
1 | function bind(obj, eventStr, func){ |
事件对象
当事件的响应函数被触发时,浏览器会将事件对象传入响应函数(IE9+),事件对象中封装了事件的信息。事件对象也会作为window的event属性保存(火狐除外)。
1 | div.onmousemove = function(event){ |
事件
onload
表示加载完成,响应函数会在页面加载完成后调用。1
2window.onload = function(){
}onsroll
滚动条滚动。onmousewheel
鼠标滚轮滚动。- 火狐不支持,需要用
addEventListener()
加入DOMMouseScroll
。 - 浏览器若有滚动条也会一起滚,要设置
return false
。 addEventListener()
绑定的事件无法用return false
取消默认行为,可以用event.preventDefault()
。- IE8不支持
event.preventDefault()
。1
2obj.onmousewheel = func;
bind(obj, "DOMMouseScroll", obj.onmousewheel);
- 火狐不支持,需要用
onmousemove
鼠标移动。onmousedown
鼠标按下。- 浏览器会默认在搜索引擎中搜索内容,可以用
return false
取消这一默认行为(IE9+)。 - 在IE8可以使用只有IE支持的
setCapture()
。其将下一次的任意鼠标按下事件变为对自身的按下事件。releaseCapture()
释放捕获。1
2obj.setCapture && obj.setCapture();
obj.releaseCapture && obj.releaseCapture();
- 浏览器会默认在搜索引擎中搜索内容,可以用
onmouseup
鼠标松开。
1 | function drag(obj) {//构建一个可以拖拽元素的函数 |
onkeydown
键盘按下。- 一般绑定给可以获取焦点的对象或document。
- 一直按会一直触发。
- 默认行为是给文本框中输入字符。
onkeyup
键盘弹起。
在<a>
的onclick事件中,如果返回false,则不会跳转。
event属性
button
鼠标按下的键。clientX
鼠标横坐标,相对于视口,下同。clientY
鼠标纵坐标pageX
鼠标横坐标,相对于页面,下同。(IE9+)pageY
鼠标纵坐标target
触发事件的节点wheelDelta
鼠标滚轮方向,向上为正。火狐使用detail
, 向上为负。alyKey
是否按下Alt。ctrlKey
是否按下Ctrl。shiftKey
是否按下Shift。metaKey
是否按下meta。keyCode
按键的编码。
DOM查找方法
- 文档节点
getElementById()
通过id获取一个元素节点对象getElementsByTagName()
通过标签名获取一组对象getElementsByName()
通过name属性获取一组对象getElementsByClassName()
通过类名获取一组对象(IE9+)body
<body>
标签document
<html>
标签all
所有元素getElementsByTagName("*")
同上querySelector()
根据CSS选择器查询一个元素节点对象(IE8+)querySelectorAll()
根据CSS选择器查询一组元素节点对象(IE8+)
- 元素节点
getElementdByTagName()
通过标签名获取后代节点childNodes
所有子节点,包括文本节点。HTML中标签间的空白也被算在内(IE8及以下不算空白)children
所有子元素firstChild
第一个子节点firstElementChild
第一个元素节点(IE9+)lastChild
最后一个子节点parentNode
父节点previousSibling
前一个兄弟节点previousElementSibling
前一个兄弟元素节点(IE9+)nextSibling
后一个兄弟节点
DOM修改方法
appendChild()
把新的子节点添加到指定节点removeChild()
删除子节点replaceChild()
替换子节点insertBefore()
在指定子节点前插入子节点createElement()
创建元素节点createTextNode()
创建文本节点
1 | var nli = document.createElement("li"); |
DOM操作CSS
使用元素.style.样式
。所有样式需要使用驼峰命名。这种修改和读取的是内联样式。
元素.currentStyle.样式
,获取的是当前样式。只有IE支持,返回值可能是auto
。
在其他浏览器(IE9+)中使用,总会返回具体数值:
1 | var style = getComputedStyle(obj, null);//第二个参数可传递伪元素 |
通用写法
1 | function getStyle(obj, name) |
clientHeight
可见高度,不带px
,包括内容区和内边距,下同。clientWidth
可见宽度offsetHeight
包括内容区,内边距和边框,下同。offsetHeight
offsetParent
获取用于定位的父元素offsetLeft
左偏移量offsetTop
上偏移量scrollHeight
滚动区域的完全高度。scrollWidth
滚动区域的完全宽度。scrollTop
滚动条的垂直位置。- 当
scrollTop == scrollHeight - clientHeight
时滚动条就滚动到底部了。 - 火狐等浏览器认为页面的滚动条属于
<html>
;旧版Chrome认为页面滚动条属于<body>
。
- 当
scrollLeft
滚动条的水平位置。
应该用切换类的方式切换CSS样式,使得行为与样式分离。
BOM
浏览器对象模型。
- window 浏览器窗口
- navigator 浏览器信息
- history 历史记录,只能向前和向后翻页
- location 地址栏
- screen 屏幕
所有其他对象都是window的属性。
Navigator
由于历史原因,navigator中大部分信息已经没用了。一般只用userAgent
返回的字符串来判断浏览器信息。
IE11
- Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; rv:11.0) like Gecko
IE10
- Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)
IE8
- Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)
Chrome
- Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
Edge
- Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363
可以用浏览器特有对象来判断。
IE : window.ActiveXObject
但这个对象在IE11转布尔会返回false,所以要用"ActiveXObject" in window
。
Histroy
length
浏览器中保存的URL数量。back()
回退。forward()
前进。go()
跳转到指定页面,正数向前跳,负数向后跳。
Lacation
直接打印location可以得到地址栏的完整页面。修改时会直接跳转,生成相应的历史记录。
assign()
加载新的文档,跳转到新的页面。reload()
重新加载当前页面,相当于F5。可传入true,强制清空浏览器缓存,相当于ctrl+F5。replace()
使用新的页面替代本页面,不会生成历史记录。
Window定时器
setInterval(func, time)
开启定时器,将函数每隔一段时间执行一次,单位毫秒。返回定时器的标志。clearInterval(n)
关闭定时器,传入标志。setTimeout()
延迟调用。clearTimeout()
关闭延迟调用。
article_txt