1. JS基础
1.1 JS基本语法
JavaScript每个语句后的;不是必须但是推荐添加
1.1.1 数据类型
1.1.1.1 Number
js不区分浮点数和整数,统一用Number表示
1.1.1.2 字符串
以单引号或者双引号括起来的文本,可以使用转义字符"\"在字符串内表示字符串内的单双引号
可以使用下标来获取字符串内的某个字符,如s[1]
但需要特别注意的是,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果:
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然为'Test'
字符串常用的方法
方法 | 作用 |
---|---|
toUpperCase() | 把一个字符串全部变为大写 |
toLowerCase() | 把一个字符串全部变为小写 |
indexOf() | 搜索指定字符串出现的位置,如果没有则返回-1 |
substring() | 返回指定索引区间的字串,第一个属性为起始点,第二个为结束点,结束点非必须 |
1.1.1.3 布尔值
true或false
1.1.2 值得注意的运算符
运算符 | 效果 |
---|---|
== | 它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果 |
=== | 它不会自动转换数据类型,如果数据类型不一致,返回false ,如果一致,再比较 |
因此,大部分情况下不要使用==,而应该使用===
1.1.3 特殊值
值 | 注释 |
---|---|
NaN | NaN这个特殊number和其他所有值不相等,包括自己,唯一能判断NaN 的方法是通过isNaN() 函数 |
null | 表示一个“空”的值,它和0 以及空字符串'' 不同,0 是一个数值,'' 表示长度为0的字符串,而null 表示“空” |
undefined | 未定义 |
1.1.4 数组
创建数组的方法:
var arr = [1,2,3];
new Array(1, 2, 3);
arr.length
可以获取数组长度,给它赋值也能改变数组的长度
请注意,如果通过索引赋值时,索引超过了范围,同样会引起Array
大小的变化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
常用数组的方法:
方法 | 作用 |
---|---|
indexOf | 搜索一个指定的元素的位置 |
slice() | 它截取Array 的部分元素,然后返回一个新的Array |
push和pop | push() 向Array 的末尾添加若干元素,pop() 则把Array 的最后一个元素删除掉 |
unshift和shift | 如果要往Array 的头部添加若干元素,使用unshift() 方法,shift() 方法则把Array 的第一个元素删掉,返回array的新长度 |
sort() | 数组排序,直接调用会按照默认顺序排序 |
reverse() | 反转数组 |
splice() | 修改Array 的“万能方法” |
concat() | 方法把当前的Array 和另一个Array 连接起来,并返回一个新的Array ,注意不是修改而是创建新的 |
join() | 它把当前Array 的每个元素都用指定的字符串连接起来,然后返回连接后的字符串 |
1.1.5 对象
即一组键值对形成的对象
当属性名包含特殊字符时,如middle-school,需要用'
括起来,访问这个属性也不能再用.
,而是要用obj['middle-school']
检测某个对象是否存在某个属性时,可以用in
,如:
'name' in xiaoming;
要判断一个属性是否是xiaoming
自身拥有的,而不是继承得到的,可以用hasOwnProperty()
方法:
xiaoming.hasOwnProperty('name');
1.1.6 变量
使用var申明变量,js的变量为动态的,可以从一种数据类型变化为另一种数据类型
如果不使用var定义的变量则会变成全局变量,在strict模式下将强制使用var定义变量,不使用就报错
ES6之后可以用const定义常量,const
与let
都具有块级作用域
启用strict模式的方法是在JavaScript代码的第一行写上:
'use strict';
1.1.7 条件判断
注意:JavaScript把null
、undefined
、0
、NaN
和空字符串''
视为false
,其他值一概视为true
1.1.8 循环
//FOR循环
var x = 0;
var i;
for (i=1; i<=10000; i++) {
x = x + i;
}
//for循环的一种变体:for...in...
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
};
for (var key in o) {
console.log(key); // 'name', 'age', 'city'
}
//for ... in对Array的循环得到的是String而不是Number
//while循环,先判断后执行
var x = 0;
var n = 99;
while (n > 0) {
x = x + n;
n = n - 2;
}
x; // 2500
//do while循环,先执行后判断
var n = 0;
do {
n = n + 1;
} while (n < 100);
n; // 100
1.1.9 Map和Set
由于对象的键只能是字符串,ES6推出了支持其他数据类型的Map
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
Set则为仅储存键不储存值,可以理解成不能重复没有索引的数组
var s = new Set([1, 2, 3, 3, '3']);//重复元素在`Set`中自动被过滤:
s; // Set {1, 2, 3, "3"}
s.add(4);
s; // Set {1, 2, 3, "3", 4}
s.add(4);
s; // 仍然是 Set {1, 2, 3, "3", 4}
s.delete(3);
s; // Set {1, 2, "3", 4}
1.1.1.10 iterable类型
Array
、Map
和Set
都属于iterable
类型。
使用for…of来遍历
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array,Array实际上是以索引为键的对象,当给其添加了额外的属性后就不能用for...in了(又是历史遗留问题)
console.log(x);
}
for (var x of s) { // 遍历Set
console.log(x);
}
for (var x of m) { // 遍历Map
console.log(x[0] + '=' + x[1]);
}
forEach
方法可以遍历整个iterable类型,此方法为ES5.1引入
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
console.log(element + ', index = ' + index);
});
//Set与Array类似,但Set没有索引,因此回调函数的前两个参数都是元素本身
//Map的回调函数参数依次为value、key和map本身:
1.2 函数
1.2.1 函数基础
定义函数的方式如下:
//方式一、直接定义abs()函数对象
function abs(x) {
}
//方式二、定义匿名函数并赋值给abs变量
var abs = function (x) {
};
//两种方法完全等价
注意:js允许传入比函数需要多或者少的变量,不影响函数的调用
关键字arguments
:仅起作用于函数内部,指向调用者传入的所有参数,类似array但不是array
ES6标准引入了rest
参数,可以查找出定义的参数以外的所有参数(以数组形式):
function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
TIPS:
- js中的作用域仅用于拘束函数,不能拘束for和if这类
- js会会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部,所以可以先引用后申明
- 不在任何函数内定义的变量就具有全局作用域
- 解构赋值可以快速进行赋值(需支持ES6)
在一个对象中绑定方法,称为这个对象的方法
对象.方法()
时,this指向对象
直接使用方法()
时,strict模式下为undefined,非strict模式下为windows
apply()
与call()
可以用于指定函数调用的this,唯一区别是:
apply()
把参数打包成Array
再传入;call()
把参数按顺序传入。
1.2.2 高阶函数
以函数为参数的函数成为高阶函数,一个最简单的高阶函数:
function add(x, y, f) {
return f(x) + f(y);
}
高级函数 | 作用 |
---|---|
map() | map() 对整个数组执行某个函数 |
reduce() | reduce() 将数组中的前两个值传入函数,得到结果后将结果与下一个元素继续传入函数 |
filter() | filter() 把传入的函数依次作用于每个元素,然后根据返回值是true 还是false 决定保留还是丢弃该元素。 |
sort() | 对数组进行排序,默认排序时是将数字也转换成字符串之后按字符串的ASCII顺序排序的,也可以调用自定义函数来排序,当返回值为1时调换传入的两个函数的位置。sort是修改数组而不是返回新数组 |
every() | 判断数组的所有元素是否满足测试条件 |
find() | 查找符合条件的第一个元素,如果找到了,返回这个元素,否则,返回undefined |
findIndex() | findIndex() 和find() 类似,也是查找符合条件的第一个元素,不同之处在于findIndex() 会返回这个元素的索引,如果没有找到,返回-1 |
forEach() | forEach() 和map() 类似,它也把每个元素依次作用于传入的函数,但不会返回新的数组。forEach() 常用于遍历数组,因此,传入的函数不需要返回值 |
1.2.3 闭包
将返回值设置为一个函数,返回的函数不会立即执行,而是会在调用时候才执行,因此,当函数内包含循环变量(或者会发生变化的变量)的计算的时候,这个计算会在调用时才发生。
返回函数不要引用任何循环变量,或者后续会发生变化的变量。
或者让其立即执行
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 1
f2(); // 4
f3(); // 9
闭包的意义:返回一个函数的同时可以携带一个外部无法访问的局部变量,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来
1.2.3 箭头函数
ES6新增的写法
x => x * x
上面的箭头函数相当于创建一个匿名函数:
function (x) {
return x * x;
}
其他写法
// 两个参数:
(x, y) => x * x + y * y
// 无参数:
() => 3.14
// 可变参数:
(x, y, ...rest) => {
var i, sum = x + y;
for (i=0; i ({ foo: x })
不过与直接定义匿名函数比,箭头函数的this就始终指向外层调用者了。
1.2.4 生成器generator
写法:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
调用一个generator会返回一个generator对象
可以通过next()
方法获取下一个返回的值以及是否返回完:
{value: 3, done: false}
{value: undefined, done: true}
也可以通过for…of循环generator来获取每一个返回值
for (var x of fib(10)) {
console.log(x); // 依次输出11,12,13
}
2. 标准对象
2.1 对象的类型
- number
- string
- boolean
- function
- undefined
- object【其中null、Array的类型也都是object】
2.2 包装对象
typeof new Number(123); // 'object'
new Number(123) === 123; // false
通过new来创建包装对象,其类型成为了对象
不写new时为转换函数,转换结果不是对象
- 不要使用
new Number()
、new Boolean()
、new String()
创建包装对象; - 用
parseInt()
或parseFloat()
来转换任意类型到number
; - 用
String()
来转换任意类型到string
,或者直接调用某个对象的toString()
方法;【null
和undefined
没有toString()
方法】 - 通常不必把任意类型转换为
boolean
再判断,因为可以直接写if (myVar) {...}
; typeof
操作符可以判断出number
、boolean
、string
、function
和undefined
;- 判断
Array
要使用Array.isArray(arr)
; - 判断
null
请使用myVar === null
; - 判断某个全局变量是否存在用
typeof window.myVar === 'undefined'
; - 函数内部判断某个变量是否存在用
typeof myVar === 'undefined'
。
2.3 常用对象
2.3.1 Date 时间对象
要获取系统当前时间,用:
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
也可以自己定义时间
var d = new Date(2015, 5, 19, 20, 15, 30, 123);
d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)
//其中,月份里0指1月,1指2月以此类推
var d = Date.parse('2015-06-24T19:49:22.875+08:00');
d; // 1435146562875
d.getMonth(); // 5——表示6月
d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关
d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时
2.3.2 RegExp正则表达式
指定字符类型
\d
可以匹配一个数字\w
可以匹配一个字母或数字\s
可以匹配一个空格(也包括Tab等空白符)- 要做更精确地匹配,可以用
[]
表示范围 - 用
()
表示的就是要提取的分组(Group)。比如:^(\d{3})-(\d{3,8})$
分别定义了两个组
指定数目【由其前面指定类型】
.
可以匹配任意字符*
表示任意个字符(包括0个)+
表示至少一个字符?
表示0个或1个字符{n}
表示n个字符{n,m}
表示n-m个字符
指定行结构
^
表示行的开头,^\d
表示必须以数字开头。$
表示行的结束,\d$
表示必须以数字结束。
创建一个正则表达式的方式
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');
split()
可以用正则表达式拆分字符串
'a,b;; c d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
exec()
方法可以匹配符合条件的字符串,有则返回数组,无则返回null
正则表达式为贪婪匹配,会尽可能匹配多的字符,加个?
可以让其不采用贪婪匹配
全局匹配加g,可以多次执行exec()
来搜索最匹配的项:
var r1 = /test/g;
// 等价于:
var r2 = new RegExp('test', 'g');
每次运行exec()
,正则表达式本身会更新lastIndex
属性,表示上次匹配到的最后索引
2.3.3 JavaScript Object Notation
JSON字符串必须用双引号""
,Object的键也必须用双引号""
2.3.3.1 JSON序列化
JSON.stringify(对象,筛选键值或者传入函数对键值进行处理,指定缩进用的空白字符)
也可以定义一个toJSON()方法返回JSON应该序列化的数据
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只输出name和age,并且改变了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
2.3.3.2 JSON反序列化
可以用JSON.parse()
把JSON格式的字符串变成一个JavaScript对象
2.4 面向对象编程
2.4.1原型
// 原型对象:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
function createStudent(name) {
// 基于Student原型创建一个新对象:
var s = Object.create(Student);
// 初始化新对象:
s.name = name;
return s;
}
var xiaoming = createStudent('小明');
xiaoming.run(); // 小明 is running...
xiaoming.__proto__ === Student; // true
2.4.2 构造函数
function Student(name) {
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!');
}
}
通过new来构造一个对象
var xiaoming = new Student('小明');
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!
不用new的话就是一个普通的函数
2.4.3 原型继承
function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
function Student(props) {
this.name = props.name || 'Unnamed';
}
Student.prototype.hello = function () {
alert('Hello, ' + this.name + '!');
}
function PrimaryStudent(props) {
Student.call(this, props);
this.grade = props.grade || 1;
}
// 实现原型继承链:
inherits(PrimaryStudent, Student);
// 绑定其他方法到PrimaryStudent原型:
PrimaryStudent.prototype.getGrade = function () {
return this.grade;
};
JavaScript的原型继承实现方式就是:
- 定义新的构造函数,并在内部用
call()
调用希望“继承”的构造函数,并绑定this
; - 借助中间函数
F
实现原型链继承,最好通过封装的inherits
函数完成; - 继续在新的构造函数的原型上定义新方法。
2.4.4 CLASS
这语言在ES6把以上说的继承方法封装成和java的class一样的继承方法了,不过由于ES6的支持度不广,说是不推荐用就是了。
3 浏览器
3.1 浏览器对象
对象名 | 意义 | 常用属性 | 兼容性 |
---|---|---|---|
window | 不但充当全局作用域,而且表示浏览器窗口 | innerWidth 和innerHeight 属性,可以获取浏览器窗口的内部宽度和高度;对应的,还有一个 outerWidth 和outerHeight 属性,可以获取浏览器窗口的整个宽高 | IE<=8不支持 |
navigator | 浏览器的信息 | appName:浏览器名称; appVersion:浏览器版本; language:浏览器设置的语言; platform:操作系统类型; userAgent:浏览器设定的 User-Agent 字符串 | |
screen | 屏幕的信息 | screen.width:屏幕宽度,以像素为单位; screen.height:屏幕高度,以像素为单位; screen.colorDepth:返回颜色位数,如8、16、24。 | |
location | 当前页面的URL信息 | href:URL地址 protocal:协议,如http host:主机,一般是域名或者IP port:端口 pathname:地址,如index.html search:提交的表单,如?a=1 hash:类似于#h1之类的标记 assign():加载新页面的方法 reload():重新加载当前页面 | |
document | 表示当前页面,document 对象就是整个DOM树的根节点 | title:标题 cookie:当前页面的cookie | cookie可以用httpOnly来设定禁止被js读取,这个项自IE6 SP1开始支持 |
history | 保存了浏览器的历史记录 | back():后退 forward ():前进 | 历史遗留,由于ajax的使用不推荐这么返回 |
3.2 DOM
DocumentObjectModel(文档对象模型)
常用的获取DOM节点的方法
document.getElementById()
//ID选择器
document.getElementsByTagName()
//标签选择器
document.getElementsByClassName()
//类选择器
document.querySelector('#q1')
var ps = q1.querySelectorAll('div.highlighted > p');
//selector语法,截止IE8都有限支持
3.2.1 更新DOM
innerHTML
:修改节点内整个html内容
innerText
或textContent
:会对字符串进行HTML编码,不会被解释为HTML标签,IE<9不支持textContent
p.style.color
:类似这样修改样式
3.2.2 插入DOM
appendChild
:插入父节点最后,如果节点已经存在于当前的文档树,这个节点首先会从原先的位置删除,再插入到新的位置
从头创建一个节点的话:
var
list = document.getElementById('list'),
haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);
insertBefore
:插入到指定位置
insertBefore(newElement, referenceElement);//两个参数都得是dom对象
3.2.3 删除DOM
// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true
remove后的节点还在内存里面,随时可以调用
3.3 提交表单的方式
3.3 操作文件
在HTML表单中,可以上传文件的唯一控件就是。
当一个表单包含时,表单的
enctype
必须指定为multipart/form-data
,method
必须指定为post
,浏览器才能正确编码并以multipart/form-data
格式发送表单的数据
FILE API
html5新增的api,允许js读取文件内容
HTML5的File API提供了File
和FileReader
两个主要对象,可以获得文件信息并读取文件。
3.4 AJAX 异步请求
var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象
//——————————————————————————//
//低版本IE用以下对象
var request = new ActiveXObject('Microsoft.XMLHTTP'); // 新建Microsoft.XMLHTTP对象
//——————————————————————————//
request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}
XMLHttpRequest
对象的open()
方法有3个参数,第一个参数指定是GET
还是POST
,第二个参数指定URL地址,第三个参数指定是否使用异步,默认是true
,所以不用写。
3.4.1 安全限制
JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致
解决方法:
- 通过Flash插件发送HTTP请求
- 通过在同源域名下架设一个代理服务器来转发
- JSONP
3.4.2 CORS
CORS全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源。
取决于对方服务器是否愿意给你设置一个正确的Access-Control-Allow-Origin
3.5 PROMISE 异步执行
作用是异步执行任务
调用resolve方法时,Promise的状态就变成fulfilled,即操作成功状态。后续走then
调用reject方法时,Promise的状态就变成rejected,即操作失败状态,后续走catch
then()
:然后执行【括号内需要是promise对象】
catch()
:错误时执行
all()
:同时执行多个promise,后面加then()
时,多个promise执行成功后再走then
race()
:同时执行多个promise,后面加then()
时,多个promise第一个执行成功后就走then
3.6 Canvas 绘图
H5新组件
getContext('2d')
:绘制2d图形
getContext("webgl")
:绘制3d图形
4 jQuery
1.x版本——支持IE6-8
2.x版本——不支持IE6-8
\$被占用怎么办——jQuery.noConflict()
可以还原\$这个变量【jq在占用\$前事先储存了它】
4.1 选择器
var div = $('#abc');//按ID来查
var ps = $('p');//按TAG来查
var a = $('.red'); //按class来查
var a = $('.red.green'); //按多个class来查 注意没有空格!
var email = $('[name=email]'); //按属性来查
var icons = $('[name^=icon]'); // 找出所有name属性值以icon开头的DOM
// 例如: name="icon-1", name="icon-2"
var names = $('[name$=with]'); // 找出所有name属性值以with结尾的DOM
// 例如: name="startswith", name="endswith"
$('p,div'); // 查多项,把和
都选出来
$('ul.lang li');//层级选择
$('parent>child') //子选择器,两者必须为直属父子关系
$('ul.lang li:first-child'); //过滤器Filter
4.2 表单相关
针对表单元素,jQuery还有一组特殊的选择器:
:input
:可以选择
,
,
和
;:file
:可以选择
,和input[type=file]
一样;:checkbox
:可以选择复选框,和input[type=checkbox]
一样;:radio
:可以选择单选框,和input[type=radio]
一样;:focus
:可以选择当前输入焦点的元素,例如把光标放到一个
上,用$('input:focus')
就可以选出;:checked
:选择当前勾上的单选框和复选框,用这个选择器可以立刻获得用户选择的项目,如$('input[type=radio]:checked')
;:enabled
:可以选择可以正常输入的
、
等,也就是没有灰掉的输入;:disabled
:和:enabled
正好相反,选择那些不能输入的。
find()
查找目标节点
filter()
方法可以过滤掉不符合选择器条件的节点
map()
方法把一个jQuery对象包含的若干DOM节点转化为其他对象
first()
、last()
和slice()
方法可以返回一个新的jQuery对象
4.3 操作DOM
$('#test').text(); // 获取文本,传入参数则修改
$('#test').html(); // 获取HTML,传入参数则修改
$('#test').css('background-color', '#ffd351').css('color', 'red');//修改样式
var div = $('#test-div');
div.hasClass('highlight'); // false, class是否包含highlight
div.addClass('highlight'); // 添加highlight这个class
div.removeClass('highlight'); // 删除highlight这个class
div.attr('name', 'Hello'); // div的name属性变为'Hello'
div.removeAttr('name'); // 删除name属性
textarea.val(); // 'Hello'
textarea.val('Hi'); // 文本区域已更新为'Hi'
ul.append(ps);//添加节点到最后
ul.prepend(ps)//添加节点到最前
li.remove(); // 所有全被删除
4.4 事件
a.on('click', function () {
alert('Hello!');
});
a.click(function () {
alert('Hello!');
});//点击事件的两种写法
$(document).ready(function () {
});
$(function () {
});//整个文档加载完之后再执行的写法
$(function () {
$('#testMouseMoveDiv').mousemove(function (e) {
$('#testMouseMoveSpan').text('pageX = ' + e.pageX + ', pageY = ' + e.pageY);
});
});//传入事件参数
off('click', function)//解除绑定
- 事件的触发总是由用户操作引发的,由JS引发的变化
change
不会检测到 - 在浏览器中,有些JavaScript代码只有在用户触发下才能执行,例如,
window.open()
函数
4.5 动画
函数 效果 show()
和hide()
左上角逐渐展开或收缩 slideUp()
和slideDown()
垂直方向逐渐展开或收缩 fadeIn()
和fadeOut()
淡入淡出 animate()
自定义动画
4.6 AJAX
ajax(url, settings)
函数需要接收一个URL和一个可选的settings
对象,常用的选项如下:
- async:是否异步执行AJAX请求,默认为
true
,千万不要指定为false
; - method:发送的Method,缺省为
'GET'
,可指定为'POST'
、'PUT'
等; - contentType:发送POST请求的格式,默认值为
'application/x-www-form-urlencoded; charset=UTF-8'
,也可以指定为text/plain
、application/json
; - data:发送的数据,可以是字符串、数组或object。如果是GET请求,data将被转换成query附加到URL上,如果是POST请求,根据contentType把data序列化成合适的格式;
- headers:发送的额外的HTTP头,必须是一个object;
- dataType:接收的数据格式,可以指定为
'html'
、'xml'
、'json'
、'text'
等,缺省情况下根据响应的Content-Type
猜测。
4.7 编写拓展
$.fn.highlight1 = function () {
// this已绑定为当前jQuery对象:
this.css('backgroundColor', '#fffceb').css('color', '#d85030');
return this;
}
//此时highlight1即可被使用为高亮函数
5 错误处理
5.1 try … catch … finally
有错误发生时,执行流程像这样:
- 先执行
try { ... }
的代码; - 执行到出错的语句时,后续语句不再继续执行,转而执行
catch (e) { ... }
代码; - 最后执行
finally { ... }
代码。
而没有错误发生时,执行流程像这样:
- 先执行
try { ... }
的代码; - 因为没有出错,
catch (e) { ... }
代码不会被执行; - 最后执行
finally { ... }
代码。
throw new Error('输入错误');
//可以主动抛出错误
5.2 捕获错误
函数的报错会往调用层往上传播,因此不需要再每个函数都设置捕获错误,可以在最顶层之类的地方捕获。
function main(s) {
console.log('BEGIN main()');
try {
foo(s);
} catch (e) {
console.log('出错了:' + e);
}
console.log('END main()');
}
function foo(s) {
console.log('BEGIN foo()');
bar(s);
console.log('END foo()');
}
function bar(s) {
console.log('BEGIN bar()');
console.log('length = ' + s.length);
console.log('END bar()');
}
main(null);
5.3 异步错误处理
异步函数执行时会出现捕获不到错误的情况,同样,绑定事件的函数也是一样的。
6 underscore
underscore是一个成熟的第三方开源库,提供了一套完善的函数式编程的接口,让我们更方便地在JavaScript中实现函数式编程,underscore会把自身绑定到唯一的全局变量_
上,这也是其名字由来
6.1 Collections集合类
集合类是指Array和Object,暂不支持Map和Set
6.1.1 map/filter
js的map函数参见【1.2.2 高阶函数】
underscore的map()
和filter()
也可以作用于Object
6.1.2 every / some
当集合的所有元素都满足条件时,_.every()
函数返回true
,当集合的至少一个元素满足条件时,_.some()
函数返回true
6.1.3 max / min
这两个函数直接返回集合中最大和最小的数,如果集合是Object,max()
和min()
只作用于value,忽略掉key
6.1.4 groupBy
groupBy()
把集合的元素按照key归类
'use strict';
var scores = [20, 81, 75, 40, 91, 59, 77, 66, 72, 88, 99];
var groups = _.groupBy(scores, function (x) {
if (x < 60) {
return 'C';
} else if (x < 80) {
return 'B';
} else {
return 'A';
}
});
// 结果:
// {
// A: [81, 91, 88, 99],
// B: [75, 77, 66, 72],
// C: [20, 40, 59]
// }
6.1.5 shuffle / sample
shuffle()
用洗牌算法随机打乱一个集合
6.2 Arrays
underscore为Array
提供了许多工具类方法,可以更方便快捷地操作Array
6.2.1 first / last
分别取第一个和最后一个元素
6.2.2 flatten
flatten()
接收一个Array
,无论这个Array
里面嵌套了多少个Array
,flatten()
最后都把它们变成一个一维数组
6.2.3 zip / unzip
'use strict';
//变数组
var names = ['Adam', 'Lisa', 'Bart'];
var scores = [85, 92, 59];
_.zip(names, scores);
// [['Adam', 85], ['Lisa', 92], ['Bart', 59]]
var namesAndScores = [['Adam', 85], ['Lisa', 92], ['Bart', 59]];
_.unzip(namesAndScores);
// [['Adam', 'Lisa', 'Bart'], [85, 92, 59]]
6.2.4 object
'use strict';
//变对象
var names = ['Adam', 'Lisa', 'Bart'];
var scores = [85, 92, 59];
_.object(names, scores);
// {Adam: 85, Lisa: 92, Bart: 59}
6.2.5 range
快速生成序列
'use strict';
// 从0开始小于10:
_.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 从1开始小于11:
_.range(1, 11); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// 从0开始小于30,步长5:
_.range(0, 30, 5); // [0, 5, 10, 15, 20, 25]
// 从0开始大于-10,步长-1:
_.range(0, -10, -1); // [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
6.3 Functions
6.3.1 bind
当用一个变量fn
指向一个对象的方法时,直接调用fn()
是不行的,因为丢失了this
对象的引用。用bind
可以修复这个问题。
'use strict';
var s = ' Hello ';
var fn = _.bind(s.trim, s);
fn();
// 输出Hello
6.3.2 partial
partial()
就是为一个函数创建偏函数,目的是将原函数的某些参数固定住,可以降低新函数调用的难度
6.3.3 memoize
memoize()
就可以自动缓存函数计算的结果:
'use strict';
var factorial = _.memoize(function(n) {
console.log('start calculate ' + n + '!...');
var s = 1, i = n;
while (i > 1) {
s = s * i;
i --;
}
console.log(n + '! = ' + s);
return s;
});
// 第一次调用:
factorial(10); // 3628800
// 注意控制台输出:
// start calculate 10!...
// 10! = 3628800
// 第二次调用:
factorial(10); // 3628800
// 控制台没有输出
6.3.4 once
once()
保证某个函数执行且仅执行一次
6.3.5 delay
delay()
可以让一个函数延迟执行,效果和setTimeout()
是一样的,但是代码明显简单了:
'use strict';
// 2秒后调用alert():
_.delay(alert, 2000);
6.4 Object
6.4.1 keys / allKeys
keys()
可以非常方便地返回一个object自身所有的key,但不包含从原型链继承下来的,allkeys()
则包含所有的
6.4.2 values
values()
返回object自身但不包含原型链继承的所有值
6.4.3 mapObject
mapObject()
就是针对object的map版本:
'use strict';
var obj = { a: 1, b: 2, c: 3 };
// 注意传入的函数签名,value在前,key在后:
_.mapObject(obj, (v, k) => 100 + v); // { a: 101, b: 102, c: 103 }
6.4.4 invert
invert()
把object的每个key-value来个交换,key变成value,value变成key
6.4.5 extend / extendOwn
extend()
把多个object的key-value合并到第一个object并返回:
'use strict';
var a = {name: 'Bob', age: 20};
_.extend(a, {age: 15}, {age: 88, city: 'Beijing'}); // {name: 'Bob', age: 88, city: 'Beijing'}
// 变量a的内容也改变了:
a; // {name: 'Bob', age: 88, city: 'Beijing'}
注意:如果有相同的key,后面的object的value将覆盖前面的object的value。
extendOwn()
和extend()
类似,但获取属性时忽略从原型链继承下来的属性。
6.4.6 clone
复制对象,但是是浅复制,两个对象相同的key所引用的value其实是同一对象
6.4.7 isEqual
对两个object进行深度比较,如果内容完全相同,则返回true
,也可以比较array
6.5 Chaining
可以把对象包装成能进行链式调用的方法。