No1:
【window】全局作用域,而且表示浏览器窗口
innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高
outerWidth和outerHeight属性,可以获取浏览器窗口的整个宽高
No2:
【navigator】表示浏览器的信息
appName属性:浏览器名称
appVersion属性:浏览器版本
language属性:浏览器设置的语言
platform属性:操作系统类型
userAgent属性:浏览器设定的User-Agent字符串
No3:
【screen】表示屏幕的信息
width属性:屏幕宽度,单位像素
height属性:屏幕高度,单位像素
colorDepth属性:颜色位数,如8/16/24
No4:
【location】当前页面的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()--重新加载当前页面
No5:
【document】表示当前页面
title属性:浏览器窗口的标题
getElementById()和getElementByTagName()可以按ID获得一个DOM节点和按Tag名称获得一组DOM节点
cookie属性可以获取当前页面的cookie,注意:设定了httpOnly
的Cookie将不能被JavaScript读取
No6:
// 返回ID为'test'的节点: var test = document.getElementById('test'); // 先定位ID为'test-table'的节点,再返回其内部所有tr节点: var trs = document.getElementById('test-table').getElementsByTagName('tr'); // 先定位ID为'test-div'的节点,再返回其内部所有class包含red的节点: var reds = document.getElementById('test-div').getElementsByClassName('red'); // 获取节点test下的所有直属子节点: var cs = test.children; // 获取节点test下第一个、最后一个子节点: var first = test.firstElementChild; var last = test.lastElementChild;
// 通过querySelector获取ID为q1的节点: var q1 = document.querySelector('#q1'); // 通过querySelectorAll获取q1节点内的符合条件的所有节点: var ps = q1.querySelectorAll('div.highlighted > p');
No7:
严格地讲,我们这里的DOM节点是指Element
,但是DOM节点实际上是Node
,在HTML中,Node
包括Element
、Comment
、CDATA_SECTION
等很多种,以及根节点Document
类型,但是,绝大多数时候我们只关心Element
,也就是实际控制页面结构的Node
,其他类型的Node
忽略即可。根节点Document
已经自动绑定为全局变量document
No8:
【更新DOM】
第一种:innerHTML(可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树)
// 获取<p id="p-id">...</p> var p = document.getElementById('p-id'); // 设置文本为abc: p.innerHTML = 'ABC'; // <p id="p-id">ABC</p> // 设置HTML: p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ'; // <p>...</p>的内部结构已修改
第二种: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>
注意:两者的区别在于读取属性时,innerText
不返回隐藏元素的文本,而textContent
返回所有文本。另外注意IE<9不支持textContent
。
No9:
DOM节点的style
属性对应所有的CSS,可以直接获取或设置
// 获取<p id="p-id">...</p> var p = document.getElementById('p-id'); // 设置CSS: p.style.color = '#ff0000'; p.style.fontSize = '20px'; p.style.paddingTop = '2em';
No10:
【插入DOM】
【appendChild】把一个子节点添加到父节点的最后一个子节点
<!-- HTML结构 --> <p id="js">JavaScript</p> <div id="list"> <p id="java">Java</p> <p id="python">Python</p> <p id="scheme">Scheme</p> </div>
var js = document.getElementById('js'), list = document.getElementById('list'); list.appendChild(js);
运行结果
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="python">Python</p> <p id="scheme">Scheme</p> <p id="js">JavaScript</p> </div>
或者
var list = document.getElementById('list'), haskell = document.createElement('p'); haskell.id = 'haskell'; haskell.innerText = 'Haskell'; list.appendChild(haskell);
运行结果
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="python">Python</p> <p id="scheme">Scheme</p> <p id="haskell">Haskell</p> </div>
【insertBefore】使用parentElement.insertBefore(newElement, referenceElement);
,子节点会插入到referenceElement
之前。
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="python">Python</p> <p id="scheme">Scheme</p> </div>
var list = document.getElementById('list'), ref = document.getElementById('python'), haskell = document.createElement('p'); haskell.id = 'haskell'; haskell.innerText = 'Haskell'; list.insertBefore(haskell, ref);
运行结果
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="haskell">Haskell</p> <p id="python">Python</p> <p id="scheme">Scheme</p> </div>
循环一个父节点的所有子节点,可以通过迭代children
属性实现
var i, c, list = document.getElementById('list'); for (i = 0; i < list.children.length; i++) { c = list.children[i]; // 拿到第i个子节点 }
No11:
要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild
把自己删掉:
// 拿到待删除节点: var self = document.getElementById('to-be-removed'); // 拿到父节点: var parent = self.parentElement; // 删除: var removed = parent.removeChild(self); removed === self; // true
删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。
No12:
【表单】
-
文本框,对应的
<input type="text">
,用于输入文本; -
口令框,对应的
<input type="password">
,用于输入口令; -
单选框,对应的
<input type="radio">
,用于选择一项; -
复选框,对应的
<input type="checkbox">
,用于选择多项; -
下拉框,对应的
<select>
,用于选择一项; -
隐藏文本,对应的
<input type="hidden">
,用户不可见,但表单提交时会把隐藏文本发送到服务器。
// <input type="text" id="email"> var input = document.getElementById('email'); input.value; // '用户输入的值'
// <input type="text" id="email"> var input = document.getElementById('email'); input.value = 'test@example.com'; // 文本框的内容已更新
提交表单
第一种:
<!-- 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>
第二种:
<!-- 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>
利用hidden修改密码为md5值
<!-- 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>
No13:
【操作文件】
当一个表单包含<input type="file">
时,表单的enctype
必须指定为multipart/form-data
,method
必须指定为post
,浏览器才能正确编码并以multipart/form-data
格式发送表单的数据。
检查文件后缀
var f = document.getElementById('test-file-upload'); var filename = f.value; // 'C:fakepath est.png' if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) { alert('Can only upload image file.'); return false; }
h5读取图片
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 + '<br>' + '大小: ' + file.size + '<br>' + '修改: ' + 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); });
No14:
JavaScript的一个重要的特性就是单线程执行模式
No15:
【AJAX】
function success(text) { var textarea = document.getElementById('test-response-text'); textarea.value = text; } function fail(code) { var textarea = document.getElementById('test-response-text'); textarea.value = 'Error code: ' + code; } var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象 request.onreadystatechange = function () { // 状态发生变化时,函数被回调 if (request.readyState === 4) { // 成功完成 // 判断响应结果: if (request.status === 200) { // 成功,通过responseText拿到响应的文本: return success(request.responseText); } else { // 失败,根据响应码判断失败原因: return fail(request.status); } } else { // HTTP请求还在继续... } } // 发送请求: request.open('GET', '/api/categories'); request.send(); alert('请求已发送,请等待响应...');
异步执行可以用回调函数实现
No16:
【Promise】承诺式
function test(resolve, reject) { var timeOut = Math.random() * 2; log('set timeout to: ' + timeOut + ' seconds.'); setTimeout(function () { if (timeOut < 1) { log('call resolve()...'); resolve('200 OK'); } else { log('call reject()...'); reject('timeout in ' + timeOut + ' seconds.'); } }, timeOut * 1000); }
这个test()
函数有两个参数,这两个参数都是函数,如果执行成功,我们将调用resolve('200 OK')
,如果执行失败,我们将调用reject('timeout in ' + timeOut + ' seconds.')
。可以看出,test()
函数只关心自身的逻辑,并不关心具体的resolve
和reject
将如何处理结果。
var p1 = new Promise(test); var p2 = p1.then(function (result) { console.log('成功:' + result); }); var p3 = p2.catch(function (reason) { console.log('失败:' + reason); });
简化为
new Promise(test).then(function (result) { console.log('成功:' + result); }).catch(function (reason) { console.log('失败:' + reason); });
Promise最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了
No17:
【Canvas】Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表、动画等
<canvas id="test-stock" width="300" height="200"> <p>Current Price: 25.51</p> </canvas>
var canvas = document.getElementById('test-shape-canvas'), ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, 200, 200); // 擦除(0,0)位置大小为200x200的矩形,擦除的意思是把该区域变为透明 ctx.fillStyle = '#00ff00'; // 设置颜色 ctx.fillRect(10, 10, 130, 130); // 把(10,10)位置大小为130x130的矩形涂色 // 利用Path绘制复杂路径: var path=new Path2D(); path.arc(75, 75, 50, 0, Math.PI*2, true); path.moveTo(110,75); path.arc(75, 75, 35, 0, Math.PI, false); path.moveTo(65, 65); path.arc(60, 65, 5, 0, Math.PI*2, true); path.moveTo(95, 65); path.arc(90, 65, 5, 0, Math.PI*2, true); ctx.strokeStyle = '#0000ff'; ctx.stroke(path);
效果图
var canvas = document.getElementById('test-text-canvas'), ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.shadowBlur = 2; ctx.shadowColor = '#666666'; ctx.font = '24px Arial'; ctx.fillStyle = '#333333'; ctx.fillText('带阴影的文字', 20, 40);
效果图
【JS实现K线图】
'use strict'; window.loadStockData = function (r) { var NUMS = 30, data = r.data; if (data.length > NUMS) { data = data.slice(data.length - NUMS); } data = data.map(function (x) { return { date: x[0], open: x[1], close: x[2], high: x[3], low: x[4], vol: x[5], change: x[6] }; }); window.drawStock(data); } window.drawStock = function (data) { var canvas = document.getElementById('stock-canvas'), width = canvas.width, height = canvas.height, ctx = canvas.getContext('2d'); console.log(JSON.stringify(data)); ctx.clearRect(0, 0, width, height); ctx.fillStyle = 'black'; ctx.fillText('Test Canvas', 10, 10); // 价格基准点 var base_price = data[0].open; // 整K的y轴基准位置 var base_y = 100; // k线图缩小比例 var scale = 4; // 日K的宽度/2 var single_width_half = 3; // 日K的宽度 var single_width_solo = single_width_half * 2; // 日K的间隔 var single_margin = 2; // 日K加间隔的宽度 var single_width = single_width_solo + single_margin; for (var i in data) { // 收盘大于开盘,涨!红色。 // 收盘小于开盘,跌!绿色。 // 收盘等于开盘,横盘!灰色。 if (data[i].close > data[i].open) { ctx.fillStyle = 'red'; ctx.strokeStyle = 'red'; } else if (data[i].close < data[i].open) { ctx.fillStyle = 'green'; ctx.strokeStyle = 'green'; } else { ctx.fillStyle = 'grey'; ctx.strokeStyle = 'grey'; } // 开/收高点 var open_close_high = data[i].open > data[i].close ? data[i].open : data[i].close; // 开/收低点 var open_close_low = data[i].open < data[i].close ? data[i].open : data[i].close; // 画开收矩形,开/收作为矩形的上下点 var rect_start = base_y - (open_close_high - base_price) / scale; var rect_height = (Math.abs(data[i].open - data[i].close)) / scale; ctx.fillRect(20 + single_width * i, rect_start, single_width_solo, rect_height); // 画高直线,当高点大于开收高点,才会有高直线 if (data[i].high > open_close_high) { var high_line_start = base_y - (data[i].high - base_price) / scale; var high_line_end = base_y - (open_close_high - base_price) / scale; ctx.beginPath(); ctx.moveTo(20 + single_width_half + single_width * i, high_line_start); ctx.lineTo(20 + single_width_half + single_width * i, high_line_end); ctx.stroke(); } // 画低直线,当低点大于开收低点,才会有低直线 if(data[i].low < open_close_low) { var low_line_start = base_y - (open_close_high - base_price) / scale; var low_line_end = base_y - (data[i].low - base_price) / scale; ctx.beginPath(); ctx.moveTo(20 + single_width_half + single_width * i, low_line_start); ctx.lineTo(20 + single_width_half + single_width * i, low_line_end); ctx.stroke(); } } }; // 加载最近30个交易日的K线图数据: var js = document.createElement('script'); js.src = 'http://img1.money.126.net/data/hs/kline/day/history/2015/0000001.json?callback=loadStockData&t=' + Date.now(); document.getElementsByTagName('head')[0].appendChild(js);
效果图
这个感觉屌屌的