Javascript学习笔记-浏览器

浏览器对象

window

window对象不但充当全局作用域,而且表示浏览器窗口。它有innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。对应的还有outerWidth和outerHeight属性,可以获取整个浏览器窗口的宽高。

navigator

navigator对象表示浏览器的信息,最常用的属性包括:

  • navigator.appName:浏览器名称;
  • navigator.appVersion:浏览器版本;
  • navigator.language:浏览器设置的语言;
  • navigator.platform:操作系统类型;
  • navigator.userAgent:浏览器设定的User-Agent字符串。

请注意,navigator的信息可以被用户修改,所以JS读取的navigator信息不一定正确。例如:

// 错误写法
var width;
if (getIEVersion(navigator.userAgent) < 9) {
    width = document.body.clientWidth;
} else {
    width = window.innerWidth;
}
// 正确写法
var width = window.innerWidth || document.body.clientWidth;
screen

screen对象表示屏幕的信息,常用的属性有:

  • screen.width:屏幕宽度,以像素为单位;
  • screen.height:屏幕高度,以像素为单位;
  • screen.colorDepth:返回颜色位数,如8、16、24。
location

location对象表示当前页面的URL信息。例如一个完整的URL:
http://www.example.com:8080/path/index.html?a=1&b=2#TOP
可以用location.href获取。要获得URL各个部分的值,可以这么写:

  • location.protocol; // 'http'
  • location.host; // 'www.example.com'
  • location.port; // '8080'
  • location.pathname; // '/path/index.html'
  • location.search; // '?a=1&b=2'
  • location.hash; // 'TOP'

加载一个新页面调用location.assign(),重新加载当前页面调用location.reload()方法。

document

document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点:

  1. document的title属性从HTML文档中的xxx读取,可以动态改变;
  2. 用document对象提供的getElementById()和getElementsByTagName()可以按ID获得一个DOM节点和按Tag名称获得一组DOM节点;
  3. document的cookie属性可以获取当前页面的Cookie。

因为HTTP协议是无状态的,服务器为了区分用户在成功登录后,会发送一个Cookie给浏览器,例如user=ABC123XYZ(加密的字符串)...,此后浏览器访问该网站时,会在请求头附上这个Cookie,服务器根据Cookie即可区分出用户。Cookie还可以存储网站的一些设置,例如,页面显示的语言等等。JS通过document.cookie读取到当前页面的Cookie:
document.cookie; // 'v=123; remember=true; prefer=zh'

由于JS能读取到页面的Cookie,而用户的登录信息通常也存在Cookie中,这就造成了巨大的安全隐患。为了确保安全,服务器端在设置Cookie时必须使用httpOnly,设定了httpOnly的Cookie将不能被JS读取,目前主流浏览器均支持httpOnly选项。

history

history对象保存了浏览器的历史记录,JS可以调用history对象的back()或forward (),相当于用户点击了浏览器的“后退”或“前进”按钮。这个对象属于历史遗留对象,对于现代Web页面来说,由于大量使用AJAX和页面交互,简单地调用history.back()可能会降低用户体验,不建议使用history这个对象。

DOM操作

JS中根节点Document已经自动绑定为全局变量document,获取DOM节点最常用的方法是document.getElementById()和document.getElementsByTagName(),以及CSS选择器document.getElementsByClassName()。此外,还有一种方法是使用querySelector()和querySelectorAll(),通过selector语法来获取节点,但不支持低版本的IE:

// 通过querySelector获取ID为q1的节点:
var q1 = document.querySelector('#q1');

// 通过querySelectorAll获取q1节点内的符合条件的所有节点:
var ps = q1.querySelectorAll('div.highlighted > p');

严格地讲,我们这里的DOM节点是指Element,但是DOM节点实际上是Node,在HTML中,Node包括Element、Comment、CDATA_SECTION等很多种,以及根节点Document类型,但是,绝大多数时候我们只关心Element,也就是实际控制页面结构的Node,其他类型的Node忽略即可。

增加DOM

JS中插入新的节点。一个是使用appendChild,把一个子节点添加到父节点的最后一个子节点。例如:


JavaScript

Java

Python

Scheme

// 把

JavaScript

添加到
的最后一项: var js = document.getElementById('js'), list = document.getElementById('list'); list.appendChild(js);

Java

Python

Scheme

JavaScript

如果节点已经存在于当前的文档,那么它会先从原先的位置删除,再插入到新的位置,更多的时候我们会重新创建一个新的节点插入到指定位置。如果我们要把子节点插入到指定的位置,可以使用parentElement.insertBefore(newElement, referenceElement):


Java

Python

Scheme

var list = document.getElementById('list'), ref = document.getElementById('python'), haskell = document.createElement('p'); haskell.id = 'haskell'; haskell.innerText = 'Haskell'; list.insertBefore(haskell, ref);

Java

Haskell

Python

Scheme

可见,使用insertBefore重点是要拿到一个“参考子节点”的引用。很多时候需要循环一个父节点的所有子节点,可以通过迭代children属性实现:

var i, c, list = document.getElementById('list');
for (i = 0; i < list.children.length; i++) {
    c = list.children[i]; // 拿到第i个子节点
}
删除DOM

JS中删除一个节点,首先要获得该节点本身以及它的父节点,然后调用父节点的removeChild把自己删掉:

// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true

这里要注意删掉的节点虽然不在文档中,但其实它还在内存中,可以随时再次被添加到别的位置。当遍历一个节点的子节点并做删除操作时,要知道children属性是一个只读属性,它在子节点变化时会实时更新,例如:

First

Second

var parent = document.getElementById('parent'); parent.removeChild(parent.children[0]); parent.removeChild(parent.children[1]); // <-- 浏览器报错 浏览器报错:parent.children[1]不是一个有效的节点。原因就在于,当

First

节点被删除后,parent.children的节点数量已经从2变为了1,索引[1]已经不存在了。
修改DOM

JS中修改节点的方法有两种:
一种是修改innerHTML属性,这个方式非常强大,不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树:

// 获取

...

var p = document.getElementById('p-id'); // 设置文本为abc: p.innerHTML = 'ABC'; //

ABC

// 设置HTML: p.innerHTML = 'ABC RED XYZ'; //

...

的内部结构已修改 用innerHTML时要注意是否需要写入HTML,如果写入的字符串是通过网络拿到了,要注意对字符编码来避免XSS攻击。

第二种是修改innerText或textContent属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标签:

// 获取

...

var p = document.getElementById('p-id'); // 设置文本: p.innerText = ''; // HTML被自动编码,无法设置一个

这种方式的缺点是扰乱了浏览器对form的正常提交,浏览器一般默认点击

注意要return true来告诉浏览器继续提交,如果return false,浏览器将不会继续提交form,这种情况通常对应用户输入有误,提示用户错误信息后终止提交form。
在检查和修改时,要充分利用来传递数据。例如,很多登录表单希望用户输入用户名和密码,但是提交表单时不传输明文密码,而是密码的MD5,直接修改密码框会显示无数个*(因为MD5有32个字符)。要想不改变用户的输入,可以利用实现:


注意没有name属性的的数据不会被提交。

操作文件

JS中上传文件使用的唯一控件是,此时表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据。
出于安全考虑,浏览器只允许用户点击选取本地文件,用JS对value赋值没有任何效果,JS也无法获得上传文件的真实路径。通常上传的文件都由后台服务器处理,JS可以在提交表单时对文件扩展名做检查,以便防止用户上传无效格式的文件:

var f = document.getElementById('test-file-upload');
var filename = f.value; // 'C:\fakepath\test.png'
if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {
    alert('Can only upload image file.');
    return false;
}

由于JS对用户上传的文件操作非常有限,尤其是无法读取文件内容,使得很多需要操作文件的网页不得不用Flash第三方插件来实现,但H5中新增的File API提供了File和FileReader两个主要对象,允许JS读取文件内容获得更多的文件信息。

var fileInput = document.getElementById('test-image-file'),
    info = document.getElementById('test-file-info'),
    preview = document.getElementById('test-image-preview');
// 监听change事件:
fileInput.addEventListener('change', function () {
    // 清除背景图片:
    preview.style.backgroundImage = '';
    // 检查文件是否选择:
    if (!fileInput.value) {
        info.innerHTML = '没有选择文件';
        return;
    }
    // 获取File引用:
    var file = fileInput.files[0];
    // 获取File信息:
    info.innerHTML = '文件: ' + file.name + '
' + '大小: ' + file.size + '
' + '修改: ' + file.lastModifiedDate; if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') { alert('不是有效的图片文件!'); return; } // 读取文件: var reader = new FileReader(); reader.onload = function(e) { var data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...' preview.style.backgroundImage = 'url(' + data + ')'; }; // 以DataURL的形式读取文件: reader.readAsDataURL(file); });

上面的代码演示了如何通过H5的File API读取文件内容。以DataURL的形式读取到的文件是一个字符串,类似于data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...常用于设置图像。如果需要服务器端处理,把字符串base64后面的字符发送给服务器并用Base64解码就可以得到原始文件的二进制信息。
在JS中,浏览器的JS执行引擎总是以单线程模式执行,执行多任务都是通过异步调用来实现,比如上面的代码 reader.readAsDataURL(file) 就会发起一个异步操作来读取文件内容。我们不知道异步操作什么时候会结束,所以要先设置一个回调函数来处理文件:

reader.onload = function(e) {
    // 当文件读取完成后,自动调用此函数:
};

你可能感兴趣的:(Javascript学习笔记-浏览器)