JS组成
- 核心:ECMAScript
- 文档对象模型(DOM) 让JS有能力与网页进行对话 DOM标准包括核心DOM和HTML DOM
- 浏览器对象模型(BOM) 让JS有能力与浏览器进行对话
JS嵌入页面方式
- 行内
- 内嵌
<scipt>...</sript>
- 链接外部.js文件
<scipt src="*.js"></sript>
注意标签中间不能加JS语句,不会执行
最好将 JavaScript 代码放在 HTML页面的底部附近,即< /body>的前面。
变量声明
声明时尽量用let或const代替var,尽量用关键字声明,否则默认是全局变量。
变量名命名规范:不允许使用关键字;可由字母,数字,下滑线及$组成;不能以字母开头
操作符
===
全等(值和类型均相等)
!==
严格不全等
数据类型
- 数字类型number
- 字符串类型string
- 由unicode字符组成,每个字符占两个字节
- 查看字符code的十六进制表现: “张”.charCodeAt().toString(16)
- 汉字起始字符 \u4e00 汉字结束字符 \u9fa5
- 转义字符\n \r回车 \t制表
string.length
string[i]
string.indexOf(substring)
返回子字符串头个字符的索引值string.slice(0, 3)
提取子字符串,从零开始不到3,取3个字符silce(2)
提取到末尾string.toLowerCase() string.toUpperCase()
不改变原值string.replace(sub1,sub2)
替换 不会更新原字符串,只会返回新字符串
- 布尔类型boolean
- 数组(内建对象)
-
三个不限制:不限制数组元素个数(长度可变);不限制下标越界:索引时不会抛出数组下标越界异常,只会显示undefined;不限制元素的数据类型(数组元素类型可混合)
-
创建:
var arr=[]; var arr=new Array(); var arr=[11,22,33]; var arr=new Array("T","R","W"); var arr=new Array(10); //长度为10
-
索引:
arr[i]
-
数组缩容:减小arr.length的数值,自动删除结尾多余元素
- 关联数组
可自定义下标;length属性失效;为hash数组,查找不用遍历,和存储位置和元素个数无关,可以快速查找元素
//创建
var city=[];
city['广东']="广州";
city['湖南']="长沙";
//遍历
for(var key in hash){
key //元素下标
hash[key] //元素值
}
- 对象(object)
创建方法一:对象声明
let person = {
name: {
first: 'Bob',
last: 'Smith'
},
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function(){
alert(this.name[0]+' '+this.name[1]+' is '+this.age+' years old. He likes '+this.interests[0]+' and '+this.interests[1]+'.');
},
greeting: function(){
alert('Hi! I\'m '+this.name[0]+'.');
}
};
person.age = 45;
person['name']['last'] = 'Cratchit';
person.eyes = 'hazel';
person.farewell = function(){
alert('Bye everybody!');
};
创建方法二:用一种称为构建函数的特殊函数来定义对象和它们的特征,函数名通常以大写字母开头
function Person(name){
this.name = name;
this.greeting = function(){
alert('Hi! I\'m '+ this.name+'.');
};
}
const person1 = new Person('Bob');
const person2 = new Person('Sarah');
创建方法三:使用Object方法
let lennon = Object();
lennon.name = "John";
lennon.year = 1940;
let Person = Object();
Person.mood = "happy";
Person.age = 20;
Person.walk(){}
Person.sleep(){}
let lennon = new Person;
创建方法四:利用create()基于现有对象创建新的对象
const person3 = Object.create(person1);
每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。原型链中的方法和属性没有被复制到其他对象,它们被访问需要通过“原型链”的方式。只有在propotype属性中的成员才会被原型链下游继承。
一般模板
// 构造器及其属性定义
function Test(a,b,c,d) {
// 属性定义
};
// 定义第一个方法
Test.prototype.x = function () { ... }
// 定义第二个方法
Test.prototype.y = function () { ... }
继承
function Teacher(first, last, age, gender, interests, subject){
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
Teacher.prototype.greeting = function(){
let prefix;
if(this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
prefix = 'Mr.';
} else if(this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
prefix = 'Mrs.';
} else {
prefix = 'Mx.';
}
alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
};
let teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
数据类型转换
typeof 变量 获取类型
isNaN(变量) 判断是否为数据类型
所有数据类型和string做+运算时,最后结果都为string
变量.toString();
parseInt(变量) 从左到右转换,遇到非整数字符则停止;若第一个即为非整数字符,结果为NaN
parseFloat(变量)
Number(字符串) 若包含非法字符,则直接返回NaN
JS在正式执行之前会提前用var声明的变量和用function声明的函数,但赋值还是在原来位置。
数组API函数
1、数组转字符串
String(arr) arr.toString() 将arr转为用逗号连接的字符串
arr.join(“连接符”) 将arr转为用自定义连接符连接的字符串 相反操作arr=str.split(’,’)
【可用于将字符组成单词,将单词组成句子,将数组转换为页面元素的内容】
2、拼接和选取
var a = a0.concat(a1,a2); 拼接两个或多个数组,并返回结果,不修改原数组
var sub = a.slice(starti, endi+1); 选取子数组,下标含头不含尾,不修改原数组; 第二个参数默认到结尾;可使用倒数下标;可用于复制数组
修改数组:arr.splice(starti, n(删除个数), 要添加的元素n1,n2,…)
要添加的元素如果是数组,直接嵌套在arr中;直接修改原数组, 若赋值给aa,aa只保存临时数组,会自动释放
arr.push(elem) 在末尾添加元素,返回新数组元素个数
arr.pop() 删除结尾元素,返回删除的元素
arr.unshift(elem) 在数组开头添加元素,返回新数组元素个数
arr.shift() 删除数组开头元素,返回删除的元素
颠倒数组:arr.reverse()
排序: arr.sort() 从小到大,默认将元素作为字符串后再排列
判断元素是否在数组中:arr.indexOf('a') != -1
arr.includes('a')
DOM(document object model)
对网页进行增删查改
查找:
document.getElementById("id");
效率非常高,只能查找一个元素parent.getElementsByTagName("tag");
查找父节点下的所有标签为tag的子节点;可用在任意父元素上;不仅直接查看子节点,而且查看所有子代节点;返回一个动态集合(只有一个元素也是数组)- 通过CSS选择器查找,返回非动态集合
只找一个元素var elem=parent.querySelector("selector")
找多个var elems=parent.querySelectorAll("selector")
修改:
修改属性:
- 读取属性值:
elem.getAttribute("属性名")
- 修改属性名:
elem.setAttribute("属性名","value")
- 判断是否包含属性:
elem.hasAttribute("属性名")
- 移除属性:
elem.removeAttribute("属性名")
修改样式:
elem.style.属性名(驼峰)=" ";
添加元素
- 创建新元素 var elem = bocument.createElement(“元素名”)
- 设置关键属性
elem.innerHTML="gohome"; a.href=""; <a href="">gohome</a>
- 设置关键样式 elem.style.fontSize=“14px”;
- 将元素添加到DOM树
parent.appendChild(newNode); 添加到最后
parent.insertBefore(newChild, existingChild); 在父元素指定子节点前添加
添加元素优化:尽量少操作DOM树
事件处理函数
onmouseover 鼠标悬停
onmouseout 鼠标离开
onmousedown 按下鼠标
onmousemove 移动鼠标
onmouseup 抬起鼠标
onclick 点击
BOM
没有标准,有兼容性问题
对象模型:
window.onload
事件:HTML文档全部加载完毕时触发的事件,可以把函数代码赋给他,注意函数不加括号,否则只是把函数结果赋过去
定时器:
周期定时器(让程序按指定时间间隔执行一项任务)
var timer=setInterval(exp, time) exp为执行语句,time单位为毫秒
clearInterval(timer); 停止定时器
一次性定时器(让程序延迟一段时间执行,不少于指定的time)
setTimeout(exp, time)
第三个参数可以传递要执行的函数的参数
clearTimeout(timer)
requestAnimationFrame()
递归调用
cancelAnimationFrame(rAF);
JQuery
快速,简洁的第三方js库;DOM操作的终极简化;屏蔽了浏览器的兼容问题。
工厂函数 $() 所有能在样式表中使用的选择符,都能放在圆括号中的引号内
性能考虑
- 尽量少访问dom,查询dom中元素每次都会搜索整个树,最好把访问后需要多次使用的量存到变量中
- 尽量少标记,过多不必要元素只会增加dom树规模,进而增加便利dom树的时间
- 合并和放置脚本。最好使用外部文件,因为外部文件与标记能清晰地分开,且浏览器也能对站点的多个页面重用缓存过的相同脚本;不建议把脚本文件分成几个文件,会增加加载页面时的请求数量;把script标签放在body关闭标签之前
- 压缩脚本,可利用专门工具软件
捕捉和冒泡
当点击一个元素时,同时也点击了他的一系列父元素。
捕捉即是从父元素的事件开始实施,一层层下来
冒泡即是从子元素的事件开始实施,一层层上去
要截断这种联系,可以使用stopPropagation()
video.onclick = function(e) {
e.stopPropagation();
video.play();
};
默认用冒泡阶段,也可以用addEventListener()
改成捕捉,将第三个参数设置为true
事件委托
异步
promise
.then().then().catch().finally()
Promise.all()
resolve() rejected()
关键字 async await
数据请求
XMLHTTPRequest 或 Fetch
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax starting point</title>
<style>
html, pre {
font-family: sans-serif;
}
body {
width: 500px;
margin: 0 auto;
background-color: #ccc;
}
pre {
line-height: 1.5;
letter-spacing: 0.05rem;
padding: 1rem;
background-color: white;
}
label {
width: 200px;
margin-right: 33px;
}
select {
width: 350px;
padding: 5px;
}
</style>
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<h1>Ajax starting point</h1>
<form>
<label for="verse-choose">Choose a verse</label>
<select id="verse-choose" name="verse-choose">
<option>Verse 1</option>
<option>Verse 2</option>
<!-- <option>Verse 3</option>
<option>Verse 4</option> -->
</select>
</form>
<h2>The Conqueror Worm, <em>Edgar Allen Poe, 1843</em></h2>
<pre>
</pre>
<script>
const verseChoose = document.querySelector('select');
const poemDisplay = document.querySelector('pre');
verseChoose.onchange = function(){
const verse = verseChoose.value;
updateDisplay(verse);
}
function updateDisplay(verse){
verse = verse.replace(' ', '').toLowerCase();
let url = verse+'.txt';
// 利用XMLHTTPRequest
// let request = new XMLHttpRequest();
// request.open('GET', url);
// request.responseType = 'text';
// request.onload = function(){
// poemDisplay.textContent = request.response;
// }
// request.send();
// 利用Fetch
fetch(url)
.then(function(response){
return response.text();
}).then(function(text){
poemDisplay.textContent = text;
});
}
updateDisplay('Verse 1');
verseChoose.value = 'Verse 1';
</script>
</body>
</html>
数据存储
- cookies 旧
- web storage(存储键值对)
- sessionStorage(浏览器关闭,数据丢失)
- localStorage(数据一直保存)
- localStorage.setItem(‘name’, ‘xiannv’)
- localStorage.getItem(‘name’)
- localStorage.removeItem(‘name’)
- indexedDB
- service worker 和 cache 离线缓存