一、HTML5中的十大新特性
1.语义标签
1.1 什么是语义化标签?
- 语义化标签既是使标签有自己的含义
1.2 语义化标签的优势
- 使界面的代码结构清晰,方便代码的阅读和团队的合作开发
- 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。
- 有利于搜索引擎优化(SEO)。
2.增强型表单

2.1 datalist的用法
<input list='food'/>
<datalist id = food>
<option value=大龙虾></option>
<option value=小龙虾></option>
<option value=汉堡包></option>
<option value=大闸蟹></option>
<option value=小笼包></option>
</datalistai>
该代码执行的样式:
2.2 progress的用法
- progress 表示定义一个进度条,用途很广泛,可以用在文件上传的进度显示,文件下载的进度显示,也可以作为一种loading的加载状态条使用。
- value 从0-max max没设置时默认为1
// 正常情况下value 为0 时的progress <progress value= 0 max= 100 ></progress>
// 当设置了value 值后progress的样式 <progress value= 50 max= 100 ></progress>
3、音频和视频
- html5提供了音频和视频文件的标准,既使用
元素。
<audio controls>//音频 <source src= type=audio> </audio>
<video controls>//视频 <source src= type=video> </video>
4、Canvas绘图
元素负责在页面中设定一个区域,然后就可以通过 JavaScript 动态地在这个区域中绘制图形
//基本语法
<canvas id=drawing width= 200 height=200>A drawing of something.</canvas>
// 在使用canvas时需要设定一个高度跟宽度将画布定下
// 文中的信息为浏览器不支持canvas标签时显示的文字
// 当画布定下后开始用JS进行画图
<script>
var drawing = document.getElementById(drawing);
//确定浏览器支持<canvas>元素
if (drawing.getContext){
// 通过getContext(2d);获取到2d的上下文对象
var context = drawing.getContext(2d);
// 通过fillRect()方法 在画布上绘制的矩形填充指定的fillstyle颜色
//绘制红色矩形
context.fillStyle = #ff0000; // 它们的默认值都是”#000000”。如果为它们指定表示颜色的字符串值,可以使用 CSS 中指定颜色值的任何格式,包括颜色名、十六进制码、rgb、 rgba、 hsl 或 hsla。
context.fillRect(10, 10, 50, 50);
//绘制半透明的蓝色矩形
context.fillStyle = rgba(0,0,255,0.5);
context.fillRect(30, 30, 50, 50);
// 传四个参数分别是矩形的 x 坐标、矩形的 y 坐标、矩形宽度和矩形高度。这些参数的单位都是像素。
}
</script>
5、svg
6、地理定位
使用getCurrentPosition()方法来获取用户的位置
可以基于此实现计算位置距离
7、拖放API
- draggable 属性为 true 时元素开启拖放
7.1 拖放事件
源对象:
- dragstart:源对象开始拖放。
- drag:源对象拖放过程中。
- dragend:源对象拖放结束。
过程对象:
- dragenter:源对象开始进入过程对象范围内。
- dragover:源对象在过程对象范围内移动。
- dragleave:源对象离开过程对象的范围。
8、Web Worker
- Web Worker 是在主线程之外运行的
- 用于解决JS单线程中,持续较长的计算,而影响用户的交互
8.1 主要用法
- 提供主线程和新线程之间数据交换的接口:postMessage、onmessage。
work.js中
// 第二步
//worker.js
onmessage =function (evt){
var data = evt.data;//通过evt.data获得发送来的数据
postMessage( data );//将获取到的数据发送会主线程
}
html 主线程
//WEB页主线程
// 第一步
var workder = new Worker(./worker.js) // 创建指向工具js的实例对象
workder.postMessage(我是主线程发送的信息)// 通过postMessage发送主线程的信息
// 第三步
worker.onmessage =function(evt){ //接收worker传过来的数据函数
console.log(evt.data); //输出worker发送来的数据
}
9、Web Storage
- Web Storage 是H5 引入的一个帮助解决cookie存储本地缓存的重要功能
- webstorage 中有5M容量,cookie只有4k
9.1 sessionStorage
session正式依赖与实现的客户端状态保持。
sessionStorage将数据保存在session中,浏览器关闭数据就消失。
9.2 localStorage
localStorage则一直将数据保存在客户端本地,除非手动删除,否则一直保存。
不管是sessionStorage,还是localStorage,可使用的API相同,常用的有如下几个(以localStorage为例):
- 保存数据:localStorage.setItem(key,value);
- 读取数据:localStorage.getItem(key);
- 删除单个数据:localStorage.removeItem(key);
- 删除所有数据:localStorage.clear();
- 得到某个索引的key:localStorage.key(index)
10、WebSocket
- WebSocket协议为web应用程序客户端和服务端之间提供了一种全双工通信机制。
- 握手阶段采用HTTP协议,在服务端与客户端初次握手时,将HTTP协议升级成WebSocket协议当链接成功时就可以在双工模式下来回传递信息
- 没有同源限制,客户端可以与任意服务器通信
- 协议标识符为wx(如果加密为wxs)
- 除了协议定义外还有JS定义,只需要链接远程主机,并建立一个WebSocket实例链接到对端的URL即可
二、JS创建对象的几种方式
1、通过{}创建对象
<script>
'use strict'; //使用strict模式
/**
使用{}创建对象,等同于 new Object();
**/
var o = {};
o.name = 'jack';
o.age = 20;
o.sayName = function(){
alert(this.name);
}
alert(o.name+'-'+o.age);
o.sayName();
</script>
如果对象不用重复创建,这种方式是比较方便的。
2、通过new Object()创建对象
<script>
// 使用 new Object() 创建对象
var o = new Object();
o.name = "zhangsna";
o.sayName = function(){
alert(this.name);
}
o.sayName();
alert('o instanceof Object>>>>>>>>>>>'+(o instanceof Object));//true
alert("typeof o >>>>> "+typeof o);//object
</script>
3、通过字变量创建对象
对象字面变量是对象定义的一种简写形式,举个例子:
var person = {name: ‘zhang’, age:20}, 这就是字面量形式,完全等价于var person = {}; person.name=‘zhang’; person.age=20;
小结:前面三种创建对象的方式存在2个问题:1.代码冗余; 2.对象中的方法不能共享,每个对象中的方法都是独立的。
4、工厂模式创建对象
这种方式是使用一个函数来创建对象,减少重复代码,解决了前面三种方式的代码冗余的问题,但是方法不能共享的问题还是存在。
<script>
// 使用工厂模式创建对象
// 定义一个工厂方法
function createObject(name){
var o = new Object();
o.name = name;
o.sayName = function(){
alert(this.name);
};
return o;
}
var o1 = createObject('zhang');
var o2 = createObject('li');
//缺点:调用的还是不同的方法
//优点:解决了前面的代码重复的问题
alert(o1.sayName===o2.sayName);//false
</script>
5、通过构造对象创建对象
所谓构造函数,也是普通的函数,不过约定俗成,构造函数的名称首字母大写,普通函数的首字母小写。通过new 构造函数来创建对象。
<script>
/**
* 构造函数模式创建对象
**/
function Person(name){
this.name = name;
this.sayName = function(){
alert(this.name);
};
}
var p1 = new Person('zhang');
var p2 = new Person('li');
p1.sayName();
p2.sayName();
alert(p1.constructor === p2.constructor);//true
alert(p1.constructor === Person);//true
alert(typeof(p1));//object
alert(p1 instanceof Object); //true
alert(p2 instanceof Object); //true
alert(p1.sayName===p2.sayName);//false
</script>
通过内存模型,可以发现,sayName函数是独立存在于每个对象的,所以p1.sayName===p2.sayName结果为false,还是没有解决方法不能共享的问题。
6、通过原型模式创建对象
每个方法中都有一个原型(prototype),每个原型都有一个构造器(constructor),构造器又指向这个方法。
<script>
/*
* 原型模式创建对象
*/
function Animal() {}
Animal.prototype.name = 'animal';
Animal.prototype.sayName = function () { alert(this.name); };
var a1 = new Animal();
var a2 = new Animal();
a1.sayName();
alert(a1.sayName === a2.sayName);//true
alert(Animal.prototype.constructor);//function Animal(){}
alert(Animal.prototype.constructor==Animal);//true
</script>
三、什么是Promise?
Promise是异步编程的一中解决方案,最早是由社区提出的,es6中正式的将其纳入,他是一个对象,可以获取到异步的操作,他相比传统的回调函数,更加的强大和合理,避免了回调地狱。
所谓的Promise,简单的来说就是一个可以存放未来才能结束的任务或者事件。
1. Promise实列有三个状态:
- pending (进行中)
- resolved (成功)
- rejected(失败)
当要处理某个任务的时候,promise的状态是pending,任务完成是状态就变成了resolved,任务失败状态就变成了rejected。
2.Promise实列有俩个过程:
- pending -- resolved (进行到成功)
- pending -- rejected (进行到失败)
状态一旦改变就不能在变成其他的状态。
3.Promise方法:
常用的方法有5中:then()、catch()、all()、race()、finally()。
1.then()
接受俩个俩个回调函数作为参数,第一个参数表示成功的时候去执行,第二参数表示失败的时候去执行,返回的时一个新的promise的实列。
2.catch()
相当于then方法的第二个参数。
3.all()
接受一个数组作为自己的参数,数组中每一项都是一个promise对象,当数组的每一个promise状态时resolved时,all方法的状态才会变成resolved,有一个变成rejected,那么all方法的状态就会变成rejected。
4.race()
他和all方法一样,接受一个数组作为自己的参数,但是不同的时他时以第一完成的promise的状态来定义直接的状态,假设第一个状态时resolved,那么race方法的状态就是resolved,反之相反。
5.finally()
他是不管promise时什么状态都会执行的都会去执行的,他不接受任何的参数。
Promise的优点:
(1)对象的状态不受外界的影响,只有异步的操作结果才能改变他的状态。 (2)一旦状态改变就不会在变,任何时候都可以得到这个结果,就如他的名字一样promise(承诺)。
Promise的缺点:
(1)无法去取消promise,只要创建就会执行,无法中途去终止。
(2)如果不设置回调函数去接受,promise内部会报错,不会映射到外部
(3)处在pending(进行中)时 ,外部无法得知进展到那一步
总结:
Promise最早是由社区提出的,在es6才被正式的纳入规范中,是为了解决异步编程的一种方案
他是一个构造函数,接受一个函数作为参数,返回一个Promise实列。他有三个状态:pending(进行中)、resolved(成功)、rejected(失败)。实列的状态只能是 pending ->resolved 和pending ->rejected ,状态一旦改变就不会在变换了。
四、继承的7种方式
想要继承,就必须要提供个父类(继承谁,提供继承的属性)例子:
//父类
function Person(name) { //给构造函数添加了参数
this.name = name
this.sum = function() {
alert(this.name)
}
}
Person.prototype.age = 10; //给构造函数添加了原型属性
1、 原型链继承
原型链继承其核心在于将父类的实例作为子类的原型
特点:
- 子类的实例也是父类的实例
- 可以方便的继承父类型的原型中的方法,但是属性的继承无意义
缺点:
- 只执行一次,无法给属性传值
- 属性的继承无意义
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sayHi = function() {
console.log('大家好,我是' + this.name);
};
//子类型
function Student() {
this.score = 100;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var s1 = new Student()
s1.sayHi() //大家好,我是undefined
console.log(s1.name); //undefined
console.log(s1.age); //undefined
console.log(s1.constructor); //student
2、借用构造函数继承
借用构造函数继承其核心是在子类的内部调用父类,通过call改变父类中this的指向,等于是复制父类的实例属性给子类
特点:
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承
- 可以方便的继承父类型的属性,但是无法继承原型中的方法
缺点:
- 实例并不是父类的实例,只是子类的实例
- 无法继承原型中的方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
//构造器
function Animation(name, age) {
this.name = name;
this.age = age;
}
Animation.prototype.eat = function() {
console.log(this.name);
}
function Cat(name, age, sex, score) {
Animation.call(this, name, age); //可以call多个父类对象
this.sex = sex;
this.score = score;
}
var c1 = new Cat('tom', 18, '男', 100); //可以传参
c1.eat(); //报错 not a function
console.log(c1 instanceof Animation); //false
console.log(c1 instanceof Cat);
3、组合继承(组合原型链继承和借用构造函数继承)
组合继承其核心是结合了两种模式的优点,传参和复用
特点:
- 可以继承父类原型上的属性,可以传参,可复用。
- 每个新实例引入的构造函数属性是私有的。
缺点:
- 调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
//组合原型链和构造函数继承
function SubType(name) {
Person.call(this, name); //借用构造函数模式
}
SubType.prototype = new Person(); //原型链继承
var sub = new SubType(gar);
console.log(sub.name); //gar继承了构造函数属性
console.log(sub.age); //继承了父类原型的属性
4、原型式继承
原型式继承其核心是用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
特点:
- 类似于复制一个对象,用函数来包装。
缺点:
- 所有实例都会继承原型上的属性。
- 无法实现复用。(新实例属性都是后面添加的)
//先封装一个函数容器,用来输出对象和承载继承的原型
function conent(obj) {
function F() {}
F.prototype = obj; //继承了传入的参数
return new F(); //返回函数对象
}
var sup = new Person() //拿到父类的实例
var sup1 = conent(sup);//这个只能生成一个对象
console.log(sup1.age); //继承了父类函数的属性
5、寄生式继承
寄生式继承其核心是就是给原型式继承外面套了个壳子。
特点:
- 没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。
缺点:
- 没用到原型,无法复用。
function content(obj) {
function F() {}
F.prototype = obj; //继承了传入的参数
return new F(); //返回函数对象
}
var sup = new Person();
//以上是原型式继承,给原型式继承套个壳子传递参数
function subobject(obj) {
var sub = content(obj);
sub.name = gar;
return sub;
}
var sup2 = subobject(sup);
//这个函数经过声明之后就成了可增添属性的对象
console.log(typeof subobject); //function
console.log(typeof sup2); //object
console.log(sup2.name); //gar,返回了个sub对象,继承了sub的属性
6、寄生组合式继承(常用)
寄生组合式继承其核心是修复了组合继承的问题
寄生:在函数内返回对象然后调用
组合:
- 函数的原型等于另一个实例。
- 在函数中用apply或者call引入另一个构造函数,可传参
//寄生
function content(obj) {
function F() {}
F.prototype = obj;
return new F();
}
//content就是F实例的另一种表示法
var con = content(Person.prototype);
//con实例( F实例)的原型继承了父类函数的原型
//上述更像是原型链继承,只不过只继承了原型属性
//组合
function Sub() {
Person.call(this); //这个继承了父类构造函数的属性
}
//解决了组合式俩次调用构造函数属性的缺点
//重点
Sub.prototype = con; //继承了con实例
con.constructor = Sub; //-定要修复实例
var sub1 = new Sub();
//Sub的实例就继承了构造函数属性,父类实例,con的函数属性
console.log(sub1.age); //10;
7、es6 中class继承
<script>
// 父类有加法方法
class Father{
constructor(x,y) {
this.x = x ;
this.y = y ;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法的方法, 同时 扩展减法方法
class Son extends Father {
constructor (x,y){
// 利用super调用父类的构造函数
// super必须在子类this之前调用
super(x,y);
this.x = x;
this.y = y;
}
subtract(){
console.log(this.x - this.y);
}
}
var son = new Son(20,10);
son.subtract();//10
son.sum(); //30
</script>
注意:this的指向问题,类里面的共有的属性和方法一定要加this使用.
- constructor中的this指向的是new出来的实例对象
- 自定义的方法,一般也指向的new出来的实例对象
- 绑定事件之后this指向的就是触发事件的事件源