Reference : JavaScript教程 - 廖雪峰的官方网站
浏览器 - 廖雪峰的官方网站
浏览器对象 - 廖雪峰的官方网站
window
对象不但充当全局作用域,而且表示浏览器窗口navigator
对象表示浏览器的信息。有时为了支持老版本的浏览器,可以利用JavaScript对不存在属性返回undefined
的特性,直接用短路运算符||
计算:
var width = window.innerWidth || document.body.clientWidth;
screen
对象表示屏幕的信息location
对象表示当前页面的URL信息,还可以用来重新加载当前页面和加载新页面document
对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document
对象就是整个DOM树的根节点。document
对象提供了getElementById()
和getElementsByTagName()
两个方法,分别可以按ID获得一个DOM节点,和按Tag名称获得一组DOM节点document
对象还有一个cookie
属性,可以获取当前页面的Cookie。Cookie是由服务器发送的key-value标示符。因为HTTP协议是无状态的,但是服务器要区分到底是哪个用户发过来的请求,就可以用Cookie来区分。当一个用户成功登录后,服务器发送一个Cookie给浏览器,例如user=ABC123XYZ(加密的字符串)...
,此后,浏览器访问该网站时,会在请求头附上这个Cookie,服务器根据Cookie即可区分出用户。
Cookie还可以存储网站的一些设置,例如,页面显示的语言等等。
JavaScript可以通过document.cookie
读取到当前页面的Cookie:
document.cookie; // 'v=123; remember=true; prefer=zh'
由于JavaScript能读取到页面的Cookie,而用户的登录信息通常也存在Cookie中,这就造成了巨大的安全隐患,这是因为在HTML页面中引入第三方的JavaScript代码是允许的:
<!-- 当前页面在wwwexample.com -->
<html>
<head>
<script src="http://www.foo.com/jquery.js"></script>
</head>
...
</html>
如果引入的第三方的JavaScript中存在恶意代码,则www.foo.com
网站将直接获取到www.example.com
网站的用户登录信息。
为了解决这个问题,服务器在设置Cookie时可以使用httpOnly
,设定了httpOnly
的Cookie将不能被JavaScript读取。这个行为由浏览器实现,主流浏览器均支持httpOnly
选项,IE从IE6 SP1开始支持。
为了确保安全,服务器端在设置Cookie时,应该始终坚持使用httpOnly
。
-
history
对象保存了浏览器的历史记录
操作DOM - 廖雪峰的官方网站
通过
getElementById()
,getElementsByTagName()
,getElementsByClassName()
方法来获取想要的一个或一组DOM节点;还可以用querySelector
和querySelectorAll
来获取DOM节点DOM是一个树形解构,操作有:更新、遍历、添加、删除
更新DOM - 廖雪峰的官方网站
修改节点的
innerHTML
属性,可以直接通过HTML片段修改DOM节点内部的子树。如果写入的字符串来自网络,注意对字符串编码(即自动将可能的代码片段转换为纯文本)来避免XSS攻击修改节点的
innerText
或textContent
属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标签
// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置文本:
p.innerText = '<script>alert("Hi")</script>';
// HTML被自动编码,无法设置一个<script>节点:
// <p id="p-id"><script>alert("Hi")</script></p>
- 修改节点的
style
属性。节点的style
属性对应所有的CSS,可以直接获取或设置。注意CSS中font-size
一类的命名需要在JavaScript用驼峰式命名为fontSize
等
// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置CSS:
p.style.color = '#ff0000';
p.style.fontSize = '20px';
p.style.paddingTop = '2em';
插入DOM - 廖雪峰的官方网站
如果是空的节点,可以直接用
innerHTML =
来修改如果节点不是空的,一个办法是用
appendChild()
,把一个子节点添加到父节点的最后一个子节点后,这时由于传入的节点是从当前文档获取的,因此节点会从原位置删除;更多的时候我们会从零创建一个新的节点,然后插入到指定位置,创建节点用document.createElement()
,插入则用appendChild()
,这样就动态地添加了一个新的节点如果我们不想把新节点放在最后,可以用
parentElement.insertBefore(newElement, referenceElement);
,新的节点会插入到referenceElement
之前
删除DOM - 廖雪峰的官方网站
- 删除的思路是找到要删除的节点和它的父节点,然后调用父节点的
removeChild
完成删除
// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true
注意删除发生后,children
属性立刻随之更新,其length
会少1
操作表单 - 廖雪峰的官方网站
HTML表单的输入控件:
- 文本框,对应的
<input type="text">
,用于输入文本; - 口令框,对应的
<input type="password">
,用于输入口令; - 单选框,对应的
<input type="radio">
,用于选择一项 - 复选框,对应的
<input type="checkbox">
,用于选择多项; - 下拉框,对应的
<select>
,用于选择一项; - 隐藏文本,对应的
<input type="hidden">
,用户不可见,但表单提交时会把隐藏文本发送到服务器。
获取值
如果我们获得了一个<input>
节点的引用,就可以直接调用value
获得对应的用户输入值:
// <input type="text" id="email">
var input = document.getElementById('email');
input.value; // '用户输入的值'
这种方式可以应用于text
、password
、hidden
以及select
。但是,对于单选框和复选框,value
属性返回的永远是HTML预设的值,而我们需要获得的实际是用户是否“勾上了”选项,所以应该用checked
判断:
// <label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
// <label><input type="radio" name="weekday" id="tuesday" value="2"> Tuesday</label>
var mon = document.getElementById('monday');
var tue = document.getElementById('tuesday');
mon.value; // '1'
tue.value; // '2'
mon.checked; // true或者false
tue.checked; // true或者false
设置值
设置值和获取值类似,对于text
、password
、hidden
以及select
,直接设置value
就可以:
// <input type="text" id="email">
var input = document.getElementById('email');
input.value = 'test@example.com'; // 文本框的内容已更新
对于单选框和复选框,设置checked
为true
或false
即可。
HTML5控件
HTML5新增了大量标准控件,常用的包括date
、datetime
、datetime-local
、color
等,它们都使用<input>标签:
<input type="date" value="2015-07-01">
<input type="datetime-local" value="2015-07-01T02:03:04">
<input type="color" value="#ff0000">
不支持HTML5的浏览器无法识别新的控件,会把它们当做type="text"
来显示。支持HTML5的浏览器将获得格式化的字符串。例如,type="date"
类型的input
的value
将保证是一个有效的YYYY-MM-DD
格式的日期,或者空字符串。
提交表单
最后,JavaScript可以以两种方式来处理表单的提交(AJAX方式在后面章节介绍)。
方式一是通过<form>
元素的submit()
方法提交一个表单,例如,响应一个<button>
的click
事件,在JavaScript代码中提交表单:
<!-- HTML -->
<form id="test-form">
<input type="text" name="test">
<button type="button" onclick="doSubmitForm()">Submit</button>
</form>
<script>
function doSubmitForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 提交form:
form.submit();
}
</script>
这种方式的缺点是扰乱了浏览器对form
的正常提交。浏览器默认点击<button type="submit">
时提交表单,或者用户在最后一个输入框按回车键。因此,第二种方式是响应<form>
本身的onsubmit
事件,在提交form
时作修改:
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>
<script>
function checkForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 继续下一步:
return true;
}
</script>
注意要return true
来告诉浏览器继续提交,如果return false
,浏览器将不会继续提交form
,这种情况通常对应用户输入有误,提示用户错误信息后终止提交form
。
在检查和修改<input>
时,要充分利用<input type="hidden">
来传递数据。
例如,很多登录表单希望用户输入用户名和口令,但是,安全考虑,提交表单时不传输明文口令,而是口令的MD5。普通JavaScript开发人员会直接修改<input>
:
<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
<input type="text" id="username" name="username">
<input type="password" id="password" name="password">
<button type="submit">Submit</button>
</form>
<script>
function checkForm() {
var pwd = document.getElementById('password');
// 把用户输入的明文变为MD5:
pwd.value = toMD5(pwd.value);
// 继续下一步:
return true;
}
</script>
这个做法看上去没啥问题,但用户输入了口令提交时,口令框的显示会突然从几个变成32个(因为MD5有32个字符)。
要想不改变用户的输入,可以利用<input type="hidden">
实现:
<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
<input type="text" id="username" name="username">
<input type="password" id="input-password">
<input type="hidden" id="md5-password" name="password">
<button type="submit">Submit</button>
</form>
<script>
function checkForm() {
var input_pwd = document.getElementById('input-password');
var md5_pwd = document.getElementById('md5-password');
// 把用户输入的明文变为MD5:
md5_pwd.value = toMD5(input_pwd.value);
// 继续下一步:
return true;
}
</script>
注意到id
为md5-password
的<input>
标记了name="password"
,而用户输入的id
为input-password
的<input>
没有name
属性。没有name
属性的<input>
的数据不会被提交。
操作文件 - 廖雪峰的官方网站
HTML: <input type="file">
HTML5: File API