一、基本语法
1、JavaScript代码可以嵌在网页的任何位置,通常放在<head></head>标签里。
2、<script></script>中包含的是JavaScript代码,可以直接被浏览器执行。
3、可将JavaScript代码放在一个.js文件中,通过<script src="js文件地址"></script>。多个页面可以引用同一份js文件。同一个页面可以同时引入多个js文件,浏览器按顺序依次执行。
4、<script>标签type默认属性为text/javascript。
5、JavaScript严格区分大小写。
6、console.log("xxx"):在控制台打印出内容。
7、alert("xxx"):弹窗。
二、数据类型和变量
1、Number
(1)JavaScript不区分整数和浮点数,统一使用Number表示。
(2)NaN表示Not A Number,当无法计算结果时使用NaN表示。
(3)Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,使用Infinity表示。
2、字符串
(1)字符串是用单引号或双引号括起来的任意文本。
(2)可以使用“+”将多个字符串连接起来。
(3)字符串是不可变的。
(4)常用方法
toUpperCase():将字符串全部变为大写。
toLowerCase():将字符串全部变为小写。
indexof():指定字符串出现的位置。
substring():返回指定索引之间的字符串。
3、布尔值
(1)一个布尔值只有true和false两个值。
(2)可以使用true或false表示布尔值,也可以使用布尔运算计算出来布尔值。
4、比较运算符
(1)JavaScript允许对任何数据类型进行比较。
(2)比较运算符
==:自动转换数据类型再做比较。
===:若数据类型不一致,返回false;数据类型一致则进行比较。
(3)NaN与所有其他值都不相等,包括它自己。可通过isNaN()函数判断NaN(唯一判断方式)。
(4)比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值。
5、null和undefined
(1)null表示一个空的值,0是一个数值,''表示一个长度为0的字符串。
(2)undefined表示值未定义。仅在判断函数参数是否传递的情况下有用。
6、数组
(1)数组是一组按顺序排列的集合,集合的每个值称为元素,JavaScript的数组可以包含任意数据类型。
(2)2种表示方式:
[1,5,9,7,2]:用[]表示,元素之间使用逗号隔开。
new Array(1,2,3):使用函数Array()实现。
(3)常用方法
indexOf():搜索指定元素的位置。
slice():截取数组的部分元素(类似substring()),返回一个新的数组,起止参数包括起始索引,不包括结束索引。如果不给定slice()的参数,会从头到尾截取数组,可用来复制数组。
push():向数组的末尾添加元素。
pop():删除数组的最后一个元素。
unshift():向数组的 头部添加元素。
shift():删除数组第一个元素。
sort():对数组进行排序。
reverse():反转数组。
splice():从指定的索引开始删除若干元素,然后再从该位置添加若干元素。
concat():将当前数组与另一个数组连接起来,返回一个新的数组。
join():将当前数组的每个元素都用指定的字符串连接起来,返回连接后的字符串。如果数组的袁术不是字符串,将自动转为字符串后再进行连接。
7、对象
(1)JavaScript的对象是一组由键-值组成的无序集合。J
(2)JavaScript用{...}表示对象,xxx:xxx表示键值,用逗号隔开,最后一个键值对末尾不需要添加逗号。
var person{
name:'zhangsan',
age:18
};
(3)JavaScript对象的键都是字符串类型,值可以是任意数据类型。每个键又称为对象的属性。
(4)获取对象属性的方式:对象变量.属性名。
(5)如果属性名包含特殊字符,必须使用'xxx'括起来,访问这个属性必须用['xxx']来访问。
(6)hasOwnProperty():判断某个对象自身是否拥有某个属性。
8、变量
(1)使用“=”对变量赋值,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是只能用“var”声明一次。
(2)如果一个变量没使用“var”声明就被使用,那么这个变量就自动被声明为全局变量。
(3)使用“var”声明的变量,使用范围被限制在该变量被声明的函数体内。
9、条件判断
JavaScrip使用if(){...}else{...}进行条件判断,else语句是可选的,如果语句块只包含一个语句则可以省略{}。
10、循环
(1)for循环, 可使用break语句跳出循环。
(2)for...in:将一个对象的所有属性一次循环出来。
var person{
name:'lisi';
age:15
};
for(var key in persion){
console.log(key);
}
(3)while循环:先判断条件再执行。
(4)do...while循环:执行完后再判断条件。
11、Map
Map是一组键值对的结构,具有极快的查找速度。
var map=new map([['a',1],['b',2]]);
map.get('a');
12、Set
(1)一组key的集合(key不能重复),不存储value。(2)要创建一个Set,需要提供一个数组作为输入,或直接创建一个空Set。
(3)重复元素再Set中自动被过滤。
(4)可使用add(key)向Set中添加元素。
(5)可使用delete(key)删除Set中元素。
13、iterable
(1)遍历数组可使用下标循环,数组、Map、Set都属于iterable类型。
(2)具有iterable类型的集合可使用for...of循环(只循环集合本身的元素)来遍历。
var arr = ['A', 'B', 'C'];
var set = new Set(['A', 'B', 'C']);
var map = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) {
console.log(x);
}
for (var x of s) {
console.log(x);
}
for (var x of m) {
console.log(x[0] + '=' + x[1]);
}
(3)foreach方法:接收一个函数,每次迭代都自动回调该函数。
a.forEach(function (element, index, array) {
// element: 指向当前元素的值,index: 指向当前索引,array: 指向Array对象本身
console.log(element + ', index = ' + index);
});
三、函数
1、定义函数
(1)方式一:
function xx(y){
//函数体
}
function:指出这是一个函数定义。
xx:函数名。
y:函数参数,若有多个参数,中间以逗号隔开。
{...}:函数体,包含若干语句,也可没有语句。
(2)方式二(末尾需加上;):
var xx = function (y) {
//函数体
};
function(y):匿名函数,没有函数名。可通过变量xx调用该函数。
2、调用函数
调用函数时,按顺序传入参数
3、arguments
(1)只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。
(2)利用arguments可以获得调用者传入的所有参数。即使函数不定义任何参数,还是可以拿到参数的值。
(3)arguments最常用于判断传入参数的个数。
4、rest参数
rest参数只能写在最后,常用...标识,
5、变量作用域与解构赋值
(1)如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量。
(2)不同函数内部的同名变量互相独立,互不影响。
(3)内部函数可以访问外部函数定义的变量。
(4)函数在查找变量时从自身函数定义开始,从内向外查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将屏蔽外部函数的变量。
(5)全局作用域:不在任何函数内定义的变量就具有全局作用域。JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性。
(6)名字空间:把自己的所有变量和函数全部绑定到一个全局变量中。
(7)局部作用域:使用let声明一个块级作用域的变量。
(8)常量:const定义常量,具有块级作用域。
(9)解构赋值:可以同时对一组变量赋值。
对数组元素进行解构赋值时,多个变量要用[...]括起来。
var [x, y, z] = ['1', '2', '3'];
如果数组本身还有嵌套,嵌套层次和位置要保持一致。
let [x, [y, z]] = ['1', ['2', '3']];
解构赋值可以忽略某些元素。
let [, , z] = ['1', '2', '3'];
需要从一个对象中取出若干属性。
var person{
name:'lisi';
age:15
};
var {name} = person;
快速获取当前页面的域名和路径。
var {hostname:domain, pathname:path} = location;
6、方法
(1)在一个对象中绑定函数,称为这个对象的方法。(2)在一个方法内部,this是一个特殊变量,它始终指向当前对象。如果以对象的方法形式调用,比如person.name(),该函数的this指向被调用的对象,也就是person。如果单独调用函数,getName(),此时,该函数的this指向全局对象,也就是window 。对普通函数调用,我们通常把this绑定为null。
要保证this指向正确,必须用obj.xxx()的形式调用。
用var that = this;,就可以在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。
(3)apply()
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var person = {
name: 'zhangsan',
birth: 1990,
age: getAge
};
getAge.apply(person, []);
(4)call():把参数按顺序传入。
(5)装饰器
JavaScript的所有对象都是动态的,即使内置的函数也可以重新指向新的函数。
7、高阶函数
(1)一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。function add(x, y, f) {
return f(x) + f(y);
}
(2)map/reduce
map()方法定义在JavaScript的Array中。
Array的reduce()把一个函数作用在这个Array的[x1,x2,x3,...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算。
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
(3)filter
用于把Array的某些元素过滤掉,然后返回剩下的元素。Array的filter()也接收一个函数filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
8、箭头函数
x => x * x
相当于
function (x) {
return x * x;
}
箭头函数相当于匿名函数。包含多条语句时不能省略{...}和return。如果参数不是一个,就需要用括号()括起来。
返回一个单表达式对象:
x => ({ foo: x })
箭头函数内部的this是词法作用域,由上下文确定。this总是指向词法作用域,也就是外层调用者obj。
9、generator
(1)generator由function*定义,并且,除了return语句,还可以用yield返回多次。(2)调用generator对象的两个方法
不断地调用generator对象的next()方法。next()方法会执行generator的代码,每次遇到yield x;就返回一个对象{value: x,done: true/false},然后“暂停”。返回的value就是yield返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。当执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。
直接用for...of循环迭代generator对象,这种方式不需要判断done。
四、标准对象
1、包装对象
(1)不要使用new Number、new Boolean、new String创建包装对象;(2)用parseInt()或parseFloat()来转换任意类型到number;
(3) String()转换任意类型到 String,或者直接调用某个对象的toString()方法;
(4)通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};
(5)typeof操作符可以判断出number、boolean、function、String和undefined;
(6)判断Array要使用Array.isArray(arr);
(7)判断null请使用myVar === null;
(8)判断某个全局变量是否存在用typeof window.myVar === 'undefined';
(9)函数内部判断某个变量是否存在用typeof myVar === 'undefined'。
2、Date
在JavaScript中,Date对象用来表示日期和时间。(1)创建一个指定日期和时间的Date对象。
var d = new Date(2017,11, 1, 20, 15, 30, 123);
(2)JavaScript的月份范围用整数表示是0~11。
3、RegExp
(1)正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,就认为它“匹配”了,否则,该字符串就是不合法的。(2)在正则表达式中,如果直接给出字符,就是精确匹配。用\d可以匹配一个数字,\w可以匹配一个字母或数字,\s可以匹配一个空格(也包括Tab等空白符),.可以匹配任意字符,特殊字符在正则表达式中用\转义,^表示行的开头(^\d表示必须以数字开头),$表示行的结束(\d$表示必须以数字结束)。
(3)要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符。
(4)要做更精确地匹配,可以用[]表示范围,比如:
[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串;
[a-zA-Z\_\$][0-9a-zA-Z\_\$]*可以匹配由字母或下划线、$开头,后接任意个由一个数字、字母或者下划线、$组成的字符串,也就是JavaScript允许的变量名;
[a-zA-Z\_\$][0-9a-zA-Z\_\$]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
(5)JavaScript有两种方式创建一个正则表达式,第一种方式是直接通过/正则表达式/写出来,第二种方式是通过new RegExp('正则表达式')创建一个RegExp对象。
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');//\\相当于\
(6)分组
用()表示的就是要提取的分组。如果正则表达式中定义了组,就可以在RegExp对象上用exec()方法提取出子串来。exec()方法在匹配成功后,会返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串。exec()方法在匹配失败时返回Array。
(7)正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。
(8)JavaScript的正则表达式指定的g,表示全局匹配。全局匹配可以多次执行exec()方法来搜索一个匹配的字符串。当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引。正则表达式指定i标志,表示忽略大小写,m标志,表示执行多行匹配。
4、JSON
(1)JSON是一种数据交换格式。JavaScript内置了JSON的解析。把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串。如果接收到一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用这个对象。(2)JSON的字符串规定必须用双引号"",Object的键也必须用双引号'"。
五、面向对象编程
1、在JavaScript中,不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程。2、Object.create()方法可以传入一个原型对象,并创建一个基于该原型的新对象,但是新对象什么属性都没有。
3、创建对象
(1)JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
创建一个Array对象:
var arr = [1, 2, 3];
(2)构造函数(构造函数首字母应大写)
function Student(name) {
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!');
}
}
var xiaoming = new Student('zhangsan');
xiaoming.name;
xiaoming.hello();
如果不写new这就是一个普通函数,返回undefined。如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this,不需要在最后写return this;。
4、原型继承
JavaScript的原型继承实现方式就是:
(1)定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this;
(2)借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;
(3)继续在新的构造函数的原型上定义新方法。
5、class继承
通过extends实现。
六、浏览器
1、浏览器对象
(1)window
window对象不但充当全局作用域,而且表示浏览器窗口。window对象有innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。
(2)navigator
navigator对象表示浏览器的信息,最常用的属性包括:
navigator.appName:浏览器名称;
navigator.appVersion:浏览器版本;
navigator.language:浏览器设置的语言;
navigator.platform:操作系统类型;
navigator.userAgent:浏览器设定的User-Agent字符串。
(3)screen
screen对象表示屏幕的信息,常用的属性有:
screen.width:屏幕宽度,以像素为单位;
screen.height:屏幕高度,以像素为单位;
screen.colorDepth:返回颜色位数。
(4)location
location对象表示当前页面的URL信息。可以用location.href获取。要加载一个新页面,可以调用location.assign()。如果要重新加载当前页面,调用location.reload()。
(5)document
document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。
document的title属性是从HTML文档中的<title>xxx</title>读取的,但是可以动态改变。
要查找DOM树的某个节点,需要从document对象开始查找。最常用的查找是根据ID和Tag Name。用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
(6)history
history对象保存了浏览器的历史记录,JavaScript可以调用history对象的back()或forward (),相当于用户点击了浏览器的“后退”或“前进”按钮。
2、操作DOM
操作一个DOM节点的几个操作:(1)更新:更新该DOM节点的内容,相当于更新了该DOM节点表示的HTML的内容;(修改innerHTML属性;修改innerText或textContent属性)
(2)遍历:遍历该DOM节点下的子节点,以便进行进一步操作;
(3)添加:在该DOM节点下新增一个子节点,相当于动态增加了一个HTML节点;(使用appendChild,把一个子节点添加到父节点的最后一个子节点;使用parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前。)
(4)删除:将该节点从HTML中删除,相当于删掉了该DOM节点的内容以及它包含的所有子节点。(获得该节点本身以及它的父节点,调用父节点的removeChild把自己删掉;)
3、操作表单
(1)HTML表单的输入控件主要有以下几种:
文本框:<input type="text">,用于输入文本;
口令框:<input type="password">,用于输入口令;
单选框:<input type="radio">,用于选择一项;
复选框:<input type="checkbox">,用于选择多项;
下拉框:<select>,用于选择一项;
隐藏文本:<input type="hidden">,用户不可见,但表单提交时会把隐藏文本发送到服务器。
(2)如果我们获得了一个<input>节点的引用,就可以直接调用value获得对应的用户输入值。
// <input type="text" id="email">
var input = document.getElementById('email');
input.value;
(3)提交表单
方式一:通过<form>元素的submit()方法提交一个表单,例如,响应一个<button>的click事件,在JavaScript代码中提交表单;
方式二:响应<form>本身的onsubmit事件,在提交form时作修改;