一、Javascript简介:
JavaScript是一种属于网络的解释型的脚本语言,已经被广泛用于Web应用开发。最早是在HTML网页上使用,用来给HTML网页增加各式各样的动态功能。在过去,JavaScript只是被用来做一些简单的网页效果,比如表单验证、浮动广告等,所以那时候JavaScript并没有受到重视。自从AJAX开始流行后,人们发现利用JavaScript可以给用户带来更好的体验,甚至利用这一优点开发了大型网页游戏,于是这门语言被重视了起来。
二、Javascript代码存放的位置
1、JavaScript代码可以直接嵌在网页的任何地方,不过通常我们把Javascript代码放在中。
2、可以将JavaScript代码放到一个单独.js文件中,如将文件命名为:script.js那么引用方式为:
<script type = "text/javascript" src = "script.js" />
三、Javascript中的数据类型
Javascript脚本语言同其他语言一样,有它自身的基本数据类型,表达式和算术运算符及程序的基本程序框架。Javascript提供了五种基本的数据类型
Number、String、Boolean、null、undefined
两种特殊数据类型
Array、Object
用来处理数据和文字。
1、Number
JavaScript不区分整数和浮点数,统一用Number表示。Number可以直接做四则运算。
2、String
字符串是以单引号 ’ 或双引号 " 括起来的任意文本,比如’abc’,“xyz"等等。需注意,''或”"本身只是一种表示方式,不是字符串的一部分,因此,字符串’abc’只有a,b,c这3个字符。
3、Boolean
布尔值和布尔代数的表示完全一致,一个布尔值只有true、false两种值,要么是true,要么是false。
4、Null
null表示一个“空”的值,它和0以及空字符串’‘不同,0是一个数值,’'表示长度为0的字符串,而null表示“空”。
5、Undefined
在JavaScript中,还有一个和null类似的undefined,它表示“未定义”。
6、Arrary 数组
数组是一组按顺序排列的集合,集合的每个值称为元素。JavaScript的数组可以包括任意数据类型。例如:
[1, 2, 3.14, 'Hello', null, true];
7、Object 对象
JavaScript的对象是一组由键-值组成的无序集合。JavaScript对象的键都是字符串类型,值可以是任意数据类型。例如:
var person = {
name: 'Bob',
age: 20,
tags: 'js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
};
Javascript 标识符可以使用数字、大小写字母,下划线,美元符号构成,标识符不能以数字开头。JavaScipt严格区分大小写,代码必须以分号结束。
四、Javascript中的****函数
1、方法
在一个对象中绑定函数,称为这个对象的方法。
在JavaScript中,对象的定义是这样的:
var xiaoming = {
name: '小明',
birth: 1990
};
但是,如果我们给xiaoming绑定一个函数,就可以做更多的事情。比如,写个age()方法,返回xiaoming的年龄:
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
xiaoming.age;
xiaoming.age();
2、高阶函数
JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
(1)、 map()
举例说明,比如我们有一个函数f(x)=x*x,要把这个函数作用在一个数组[1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map实现如下:
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果:
(2)、 reduce()
Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,
比方说对一个Array求和,就可以用reduce实现:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
(3)、 filter()
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
例如,在一个Array中,删掉偶数,只保留奇数,可以这么写:
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
(4)、 sort()
JavaScript的Array的sort()方法就是用于排序的,但是排序结果可能让你大吃一惊:
// 看上去正常的结果:
['Google', 'Apple', 'Microsoft'].sort(); // ['Apple', 'Google', 'Microsoft'];
// apple排在了最后:
['Google', 'apple', 'Microsoft'].sort(); // ['Google', 'Microsoft", 'apple']
// 无法理解的结果:
[10, 20, 1, 2].sort(); // [1, 10, 2, 20]
这是因为Array的sort()方法默认把所有元素先转换为String再排序。sort()方法也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。
例如:要按数字大小排序,我们可以这么写:
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); // [1, 2, 10, 20]
2、闭包
闭包(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的用处,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
(1)、读取函数内部的变量
例如:
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
把f2作为返回值,我们就可以在f1外部读取它的内部变量
(2)、将变量的值始终保持在内存中
例如:
function f1() {
var n = 999;
nAdd = function () { n += 1 }
function f2() {
alert(n);
}
return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回收。
4、箭头函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
为什么叫Arrow Function?因为它的定义用的就是一个箭头:
x => x * x
//上面的箭头函数相当于:
function (x) {
return x * x;
}
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ … }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ … }和return:
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
//如果参数不是一个,就需要用括号()括起来:
(x, y) => x * x + y * y
5、generator
generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。
generator跟函数很像,定义如下:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
generator和函数不同的是,generator由function定义(注意多出的号),并且,除了return语句,还可以用yield返回多次。
五、标准对象
1、Date
在JavaScript中,Date对象用来表示日期和时间。
要获取系统当前时间,用:
var now = new Date();
now;//Tue Nov 01 2020 11:34:14 GMT+0800(中国标准时间)
now.getFullYear(); // 2020 年份
now.getMonth(); // 10, 月份,注意月份范围是0~11,10表示11月
now.getDate(); // 1, 表示1号
now.getDay(); // 2, 表示星期二
now.getHours(); // 11, 24小时制
now.getMinutes(); // 30, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 490, 毫秒数
now.getTime(); // 1477971254490, 以number形式表示的时间戳
注意,当前时间是浏览器从本机操作系统获取的时间,所以不一定准确,因为用户可以把当前时间设定为任何值。
如果要创建一个指定日期和时间的Date对象,可以用:
var d = new Date(2016, 5, 19, 20, 15, 30, 123);
d; // Fri Jun 19 2016 20:15:30 GMT+0800 (CST)
2、RegExp
正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
在javascript我们可以通过内建的类来定义一个正则表达式。
var reName = new RegExp();
在javascript中处理正则表达式的方法。
test – RegExp的test方法用来测试字符串是否匹配给出的匹配模式,返回布尔值;
exec – RegExp的exec方法返回包含第一个匹配的的数组或null;
match – String的match方法返回包含所有匹配子字符串的数组;
replace – String的replace方法完成string的替换操作,支持正则表达式;
search – 与String的indexof方法类似,不同的是search支持正则表达式,而不仅仅是字符串;
split – 按照一定规则拆分字符串并将子字符串存储到数组中的String方法。
关于这些函数的具体使用方法,可以参阅JS的相关函数手册。
3、JSON
JSON是JavaScript Object Notation的缩写,它是一种数据交换格式。在JSON中有以下几种数据类型:
number:和JavaScript的number完全一致;
boolean:就是JavaScript的true或false;
string:就是JavaScript的string;
null:就是JavaScript的null;
array:就是JavaScript的Array表示方式——[];
object:就是JavaScript的{ … }表示方式。
以及上面的任意组合。
并且,JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号"“,Object的键也必须用双引号”"。
序列化
让我们先把小明这个对象序列化成JSON格式的字符串:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
JSON.stringify(xiaoming,null,’’);
结果:
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
第二个参数用于控制如何筛选对象的键值,如果我们只想输出指定的属性,可以传入Array:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
结果:
{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
六、面向对象编程
JavaScript的所有数据都可以看成对象,不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。
1、创建对象的几种方法
(1)、使用对象字面量的方式{}创建一个对象
var Cat = {};
Cat.name="kity";//添加属性并赋值
Cat.age=2;
Cat.sayHello=function(){
alert("hello "+Cat.name+",今年"+Cat["age"]+"岁了");//可以使用“.”的方式访问属性,也可以使用HashMap的方式访问
}
Cat.sayHello();//调用对象的(方法)函数
(2)、用构造函数创建对象
function Person(){
}
var personOne=new Person();//定义一个function,如果有new关键字去"实例化",那么该function可以看作是一个类
personOne.name="dylan";
personOne.hobby="coding";
personOne.work=function(){
alert(personOne.name+" is coding now...");
}
personOne.work();
(3)、使用原型模式创建对象
function Dog(){
}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){
alert(this.name+"是个吃货");
}
var wangcai =new Dog();
wangcai.eat();
2、class继承
新的关键字class从ES6开始正式被引入到JavaScript中。class的目的就是让定义类更简单。
如果用新的class关键字来编写Student,可以这样写:
class Student {
constructor(name) {
this.name = name;
}
hello() {
alert('Hello, ' + this.name + '!');
}
}
用class定义对象的一个巨大的好处是继承更方便。现在,原型继承的中间对象,原型对象的构造函数等等都不需要考虑了,直接通过extends来实现:
class PrimaryStudent extends Student {
constructor(name, grade) {
super(name); // 记得用super调用父类的构造方法!
this.grade = grade;
}
myGrade() {
alert('I am at grade ' + this.grade);
}
}
ES6引入的class和原有的JavaScript原型继承有什么区别呢?
实际上它们没有任何区别,class的作用就是让JavaScript引擎去实现原来需要我们自己编写的原型链代码。简而言之,用class的好处就是极大地简化了原型链代码。
七、浏览器
由于JavaScript的出现就是为了能在浏览器中运行,所以,浏览器自然是JavaScript开发者必须要关注的。
1、浏览器对象
(1)、window
window对象不但充当全局作用域,而且表示浏览器窗口。
(2)、navigator
navigator对象表示浏览器的信息,最常用的属性包括:
navigator.appName:浏览器名称;
navigator.appVersion:浏览器版本;
navigator.language:浏览器设置的语言;
navigator.platform:操作系统类型;
navigator.userAgent:浏览器设定的User-Agent字符串。
(3)、screen
screen对象表示屏幕的信息,常用的属性有:
screen.width:屏幕宽度,以像素为单位;
screen.height:屏幕高度,以像素为单位;
screen.colorDepth:返回颜色位数,如8、16、24。
(4)、document
document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。
(5)、history
history对象保存了浏览器的历史记录,JavaScript可以调用history对象的back()或forward (),相当于用户点击了浏览器的“后退”或“前进”按钮。
2、操作DOM
(1)、更新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>';
两者的区别在于读取属性时,innerText不返回隐藏元素的文本,而textContent返回所有文本。另外注意IE<9不支持textContent。
(2)、插入DOM
如果这个DOM节点是空的,例如,
,那么,直接使用innerHTML = ' child'就可以修改DOM节点的内容,相当于“插入”了新的DOM节点。如果这个DOM节点不是空的,那就不能这么做,因为innerHTML会直接替换掉原来的所有子节点。可以使用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>
把
JavaScript
添加到Var js = document.getElementById('js'),
list = document.getElementById('list');
list.appendChild(js);
现在,HTML结构变成了这样:
<!-- 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>
(3)、删除DOM
要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉:
// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true
3、操作表单
(1)、获取值
如果我们获得了一个节点的引用,就可以直接调用value获得对应的用户输入值:
var input = document.getElementById('email');
input.value; // '用户输入的值'
//这种方式可以应用于text、password、hidden以及select。
(2)、设置值
设置值和获取值类似,对于text、password、hidden以及select,直接设置value就可以:
var input = document.getElementById('email');
input.value = 'test@example.com'; // 文本框的内容已更新
4、操作文件
JavaScript可以在提交表单时对文件扩展名做检查,以便防止用户上传无效格式的文件:
var f = document.getElementById('test-file-upload');
var filename = f.value; // 'C:\mypath\test.png'
if(!filename||!(filename.endsWith('.jpg')||filename.endsWith('.png') || filename.endsWith('.gif'))) {
alert('Can only upload image file.');
return false;
}
5、AJAX
AJAX不是JavaScript的规范,它是Asynchronous JavaScript and XML的缩写,意思就是用JavaScript执行异步网络请求。
用JavaScript写一个完整的AJAX代码并不复杂,但是需要注意:AJAX请求是异步执行的,也就是说,要通过回调函数获得响应。
在现代浏览器上写AJAX主要依靠XMLHttpRequest对象:
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('请求已发送,请等待响应...');
5、Promise
Promise是异步编程的一种解决方案,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
下面是一个Promise对象的简单例子:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
上面代码中,timeout方法返回一个Promise实例,表示一段时间以后才会发生的结果。过了指定的时间(ms参数)以后,Promise实例的状态变为Resolved,就会触发then方法绑定的回调函数。
下面是异步加载图片的例子:
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
上面代码中,使用Promise包装了一个图片加载的异步操作。如果加载成功,就调用resolve方法,否则就调用reject方法。
八、JQuery
jQuery是JavaScript在世界上使用最广泛的一个库。
jQuery为我们解决了一些很重要的问题。jQuery能帮我们干这些事情:
a. 消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器来绑定事件,编写AJAX等代码;
b.简洁的操作DOM的方法:写$(‘#test’)肯定比document.getElementById(‘test’)来得简洁;
c. 轻松实现动画、修改CSS等各种操作。
1、基本选择器
选择器是jQuery的核心。一个选择器写出来类似$(‘#dom-id’)。
(1)、按ID查找
如果某个DOM节点有id属性,利用jQuery查找如下:
// 查找<div id="abc">:
var div = $('#abc');
(2)、按tag查找
按tag查找只需要写上tag名称就可以了:
var ps = $('p'); // 返回所有<p>节点
ps.length; // 数一数页面有多少个<p>节点
(3)、按class查找
按class查找注意在class名称前加一个:
var a = $('.red'); // 所有节点包含class="red"都将返回
// 例如:
// <div class="red">...</div>
// <p class="green red">...</p>
通常很多节点有多个class,我们可以查找同时包含red和green的节点:
var a = $('.red.green'); // 注意没有空格!
// 符合条件的节点:
// <div class="red green">...</div>
// <div class="blue green red">...</div>
(4)、按属性查找
一个DOM节点除了id和class外还可以有很多属性,很多时候按属性查找会非常方便,比如在一个表单中按属性来查找:
var email = $('[name=email]'); // 找出<??? name="email">
var a = $('[items="A B"]'); // 找出<??? items="A B">
(5)、组合查找
组合查找就是把上述简单选择器组合起来使用。如果我们查找$(‘[name=email]’),很可能把表单外的
var emailInput = $('input[name=email]'); // 不会找出<div name="email">
2、层级选择器
如果两个DOM元素具有层级关系,就可以用$(‘ancestor descendant’)来选择,层级之间用空格隔开。例如:
<!-- HTML结构 -->
<div class="testing">
<ul class="lang">
<li class="lang-javascript">JavaScript</li>
<li class="lang-python">Python</li>
<li class="lang-lua">Lua</li>
</ul>
</div>
要选出JavaScript,可以用层级选择器:
$('ul.lang li.lang-javascript');
$('div.testing li.lang-javascript');
3、查找和过滤
最常见的查找是在某个节点的所有子节点中查找,使用find()方法,它本身又接收一个任意的选择器。例如如下的HTML结构:
<!-- HTML结构 -->
<ul class="lang">
<li class="js dy">JavaScript</li>
<li class="dy">Python</li>
<li id="swift">Swift</li>
<li class="dy">Scheme</li>
<li name="haskell">Haskell</li>
</ul>
用find()查找:
var ul = $('ul.lang'); // 获得<ul>
var dy = ul.find('.dy'); // 获得JavaScript, Python, Scheme
var swf = ul.find('#swift'); // 获得Swift
var hsk = ul.find('[name=haskell]'); // 获得Haskell
和函数式编程的map、filter类似,jQuery对象也有类似的方法。filter()方法可以过滤掉不符合选择器条件的节点:
var langs = $(‘ul.lang li’); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var a = langs.filter(‘.dy’); // 拿到JavaScript, Python, Scheme
4、操作DOM
(1)、修改Text和HTML:
jQuery对象的text()和html()方法分别获取节点的文本和原始HTML文本,例如,如下的HTML结构:
<!-- HTML结构 -->
<ul id="test-ul">
<li class="js">JavaScript</li>
<li name="book">Java & JavaScript</li>
</ul>
分别获取文本和HTML:
$('#test-ul li[name=book]').text();// 'Java & JavaScript'
$('#test-ul li[name=book]').html();//'Java& JavaScript'
(2)、修改CSS
jQuery对象有“批量操作”的特点,这用于修改CSS很方便。 考虑下面的HTML结构:
<!-- HTML结构 -->
<ul id="test-css">
<li class="lang dy"><span>JavaScript</span></li>
<li class="lang"><span>Java</span></li>
<li class="lang dy"><span>Python</span></li>
<li class="lang"><span>Swift</span></li>
<li class="lang dy"><span>Scheme</span></li>
</ul>
要高亮显示动态语言,调用jQuery对象的css(‘name’, ‘value’)方法,我们用一行语句实现:
$('#test-cssli.dy>span').css('background-color', '#ffd351').css('color', 'red');
(3)、显示和隐藏DOM
考虑到显示和隐藏DOM元素使用非常普遍,jQuery直接提供show()和hide()方法,我们不用关心它是如何修改display属性的,总之它能正常工作:
var a = $('a[target=_blank]');
a.hide(); // 隐藏
a.show(); // 显示
5、事件
jQuery能够绑定的事件主要包括:
鼠标事件
click: 鼠标单击时触发;
dblclick:鼠标双击时触发;
mouseenter:鼠标进入时触发;
mouseleave:鼠标移出时触发;
mousemove:鼠标在DOM内部移动时触发;
hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave。
键盘事件
键盘事件仅作用在当前焦点的DOM上,通常是和。
keydown:键盘按下时触发;
keyup:键盘松开时触发;
keypress:按一次键后触发。
其他事件
focus:当DOM获得焦点时触发;
blur:当DOM失去焦点时触发;
change:当、或的内容改变时触发;
submit:当提交时触发;
ready:当页面被载入并且DOM树完成初始化后触发。
例子:绑定与取消绑定事件
function hello() {
alert('hello!');
}
a.click(hello); // 绑定事件
// 10秒钟后取消绑定:
setTimeout(function () {
a.off('click', hello);
}, 10000);
九、JavaScript后端开发
1、Node.js简介
简单的说 Node.js 就是运行在服务端的JavaScript。
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
2、Node的交互模式和直接运行.js文件的区别
直接输入node进入交互模式,相当于启动了Node解释器,但是等待你一行一行地输入源代码,每输入一行就执行一行。
直接运行node hello.js文件相当于启动了Node解释器,然后一次性把hello.js文件的源代码给执行了,你是没有机会以交互的方式输入源代码的。
3、模块
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Node环境中,一个.js文件就称之为一个模块(module)。
编写模块:
//hello.js
var s = 'Hello';
function greet(name) {
console.log(s + ', ' + name + '!');
}
module.exports = greet;//作用是把函数greet作为模块的输出暴露出去,这样其他模块就可以使用greet函数了
调用模块:
//main.js
// 引入hello模块:
var greet = require('./hello');
var yx = 'yuxuan';
greet(yx); // Hello, yuxuan!
一个模块想要对外暴露变量(函数也是变量),可以用module.exports = variable;,一个模块要引用其他模块暴露的变量,用var ref = require(‘module_name’);就拿到了引用模块的变量。
4、fs模块
Node.js内置的fs模块就是文件系统模块,负责读写文件。和所有其它JavaScript模块不同的是,fs模块同时提供了异步和同步的方法。
(1)、同步读文件步骤:
- 创建一个文件 input.txt ,内容如下:
你好,我是方建康。
Hello!my name is fangjiankang.
- 创建 main.js 文件, 代码如下:
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("程序执行结束!");
- 以上代码执行结果如下:
你好,我是方建康。
Hello!my name is fangjiankang.
程序执行结束!
(2). 异步读文件步骤:
- 创建一个文件 input.txt ,内容如下:
你好,我是方建康。
Hello!my name is fangjiankang.
2. 创建 main.js 文件, 代码如下:
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序执行结束!");
- 以上代码执行结果如下:
程序执行结束!
你好,我是方建康。
Hello!my name is fangjiankang.
(3). 写文件步骤:
-
创建一个空文件 output.txt
-
创建 main.js 文件, 代码如下:
var fs = require('fs');
var data = 'Hello, Node.js';
fs.writeFile('output.txt', data, function (err) {
if (err) {
console.log(err);
} else {
console.log('ok.');
}
});
- 执行结果:空文件 output.txt里的内容变为Hello, Node.js
5、Stream模块
stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构。
Stream 有四种流类型:
Readable - 可读操作。
Writable - 可写操作。
Duplex - 可读可写操作.
Transform - 操作被写入数据,然后读出结果。
所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:
data - 当有数据可读时触发。
end - 没有更多的数据可读时触发。
error - 在接收和写入过程中发生错误时触发。
finish - 所有数据已被写入到底层系统时触发。
(1)、从流中读取数据:
1.创建 input.txt 文件,内容如下:
hello world !
2.创建 main.js 文件, 代码如下:
var fs = require("fs");
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('input.txt');
// 设置编码为 utf8。
readerStream.setEncoding('UTF8');
// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
3.以上代码执行结果如下:
程序执行完毕
hello world !
(2)、写入流:
- 创建 main.js 文件, 代码如下:
var fs = require("fs");
var data = 'hello world !';
// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("写入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
- 以上程序会将 data 变量的数据写入到 output.txt 文件中。代码执行结果如下:
程序执行完毕
写入完成。
- 查看 output.txt 文件的内容:
hello world !
6、http模块
要开发HTTP服务器程序,从头处理TCP连接,解析HTTP是不现实的。这些工作实际上已经由Node.js自带的http模块完成了。应用程序并不直接和HTTP协议打交道,而是操作http模块提供的request和response对象。
实现一个HTTP服务器程序的步骤:
1、引入requried模块:我们使用 require 指令来载入 http 模块,并将实例化的 HTTP 赋值给变量 http,实例如下:
var http = require(“http”);
2、创建服务器,接收请求与响应请求:
// 创建http server,并传入回调函数:
var server = http.createServer(function (request, response) {
// 将HTTP响应200写入response
response.writeHead(200, {'Content-Type': 'text/html'});
// 将HTTP响应的HTML内容写入response:
response.end('<h1>Hello world!</h1>');
});
// 让服务器监听8080端口:
server.listen(8080,‘127.0.0.1’);
// 终端打印如下信息
console.log(‘Server is running at http://127.0.0.1:8080/’);
3、在命令提示符下运行该程序,可以看到以下输出:
Server is running at http://127.0.0.1:8080/
4、不要关闭命令提示符,直接打开浏览器输http://127.0.0.1:8080,即可看到服务器响应的内容:
Hello world!