1.ES6新特性
1.1let & const
//变量定义
var num1=100
console.log(num)
let num2=200
const num3=100 //常量
let特点:
//let声明的变量,不能变量提升,必须先声明再使用。
//不允许重复声明变量
//let声明的变量具有 块作用域 {}
区别:
//const声明是常量 ,声明的不会改变
//let声明的时候可以不赋值,const声明的时候必须赋值
let num
num=100
console.log(num) //100
const num //这里就会报错
let 与const都不会变量提升
1.2箭头函数
简化函数写法
function fun(){
let fun=function(){}
let fun1=()=>{}
} 1.当形参只有一个时,小括号可以不写 参1 =>{}
- 当函数体只有一条语句时,大括号可以不写 参1 => console.log(参1)
- 当函数体只有一条return语句, 大括号和return都可以不写
特点: 箭头函数中的this指向应用上下文本 箭头函数中如果出现this, 它指向的上一作用域this指向的对象
<div>
<button>按钮</button>
</div>
<script>
const divEle = document.querySelector('div')
const btn = document.querySelector('button')
// btn.onclick = function(){
// console.log(this);
//这里的this指向btn
// }
// console.log(this)
divEle.onclick = function () {
btn.onclick = () => {
setTimeout(() => {
console.log(this)
}, 1000);
}
}
</script>
1.3函数传递参数的时候的默认值
我们在定义函数的时候,有的时候需要一个默认值出现,就是当我不传递参数的时候,使用默认值,传递参数了就使用传递的参数
function fun(m = 100){
console.log(m);
}
// function fun(m){
// m = m || 100 //函数参数默认值
// console.log(m);
// }
fun()
1.4解构赋值
简化访问简单对象和数组成员方式。
解构对象
var obj={
name:'jack',
age:20,
gender:'男'
}
//解析obj对象,将obj对象名为name,age,gender属性的值赋给,大括号中的同名变量
let{name,age,gender}=obj
console.log('name',name,'age',age,'gender',gender)
解构数组
//解构数组arr, 将数组中第一个开始的元素分别赋值给变量a,b,c
var arr=['jace','rose','tom']
let [a,b,c]=arr
console.log(a,b,c)
1.5展开运算符
...
用于展开数组元素或对象属性
let arr=[1,2,3]
console.log(...arr) //1 2 3
应用:
//应用:
合并数组
[1,2,3] [4,5,6]
[1,2,3,4,5,6]
例如: var arr1=[1,2,3]
var arr2=[4,5,6]
var arr3=[...arr1,...arr2] //[1,2,3,4,5,6]
1.6字面量简化
<!--
字面量简化
当简单对象的属性名和属性值同名时,只写一个
-->
<script>
let name = 'jack'
let age = 20
// let person = {
// name: name,
// age: age
// }
let person = {
name,
age
}
console.log(person);
</script>
2.面向对象编程
面向过程:分析除解决问题需要的步骤,然后按照步骤解决问题。
面向对象:把事务分解成一个个为对象,以对象功能划分问题。
面向对象特性:封装性、继承性、多态性
优缺点:
- 面向过程性能更高,和硬件联系更紧密。
- 面向对象性能虽然低,但易复用、易维护、易扩展,灵活性更高。
对象是什么?
- 一组无序的相关属性和方法组成的集合。
类抽象了对象的公共部分。
面向对象的思维特点:
- 抽取对象共用的属性和行为封装成一个类(模板)
- 对类进行实例化,创建对象。 类里面有一个最重要的函数 constructor,可以接收传递过来 的参数,同时返回实例对象,只要用new生成实例,就会自动调用。就算不写这个函数,也会被自动生成。
constructor是构造函数。
2.1类的继承
super可以调用父类的构造函数。
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(x,y); //super必须在this之前才能调用父类的函数。
this.x=x;
this.y=y;
}
}
var son = new Son(1,2);
var son1 = new Son(11,22);
son.sum();
son1.sum();
super关键字也能调用父类的普通函数。
class Father {
say(){
return '我是大大';
}
}
class Son extends Father {
say(){
console.log(super.say()+'的小小');
}
}
var son = new Son();
son.say();
//继承中,实例化子类对象输出一个方法,先看看子类有没有,若有,则执行子类;若无,则看父类有无,若有则继承执行(就近原则)
注意:
- 在es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象。
- 类里面的共有属性和方法一定要加this使用。
- constructor里面的this指向实例化对象,方法里面的this指向这个方法的调用者(调用者有可能是实例化对象,也有可能是其他。) 注意
ES6 中 class 与构造函数的关系
class 为 构造函数的语法糖,即 class 的本质是 构造函数。class的继承 extends 本质 为构造函数的原型链的继承。
例如:
类的写法
class Person{ //定义一个名字为Person的类
constructor(name,age){ //constructor是一个构造方法,用来接收参数
this.name = name; //this代表实例对象
this.age = age;
}
say(){ //这是一个类的方法,注意千万不要加上function
return this.name + this.age
}
}
var obj = new Person('老铁',18);
console.log(obj.say());
构造函数的写法
function Person(name,age){ //构造函数和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
if(!(this instanceof Person)){ //避免使用者不小心讲Person当作普通函数执行
throw new Error(''请使用 new Person"); //仿ES6 class 中的写法
}
this.name = name;
this.age = age;
}
Person.prototype.say = function(){
return this.name + this.age
}
var obj = new Person('老铁',18); //通过构造函数创建对象,必须使用new运算符
console.log(obj.say());
// 总结:通过class定义的类 和通过构造函数定义的类 二者本质相同。并且在js执行时,会将第一种转会为第二种执行。所以 ES6 class的写法实质就是构造函数。
2.2 面向对象的tab栏切换
功能需求:
对应tab栏应该实现切换,添加,删除,修改功能。
抽象对象:Tab对象
该对象具有以上切换、添加、删除、修改 功能。
其中修改功能的核心思路: 双击文字时在里面生成一个文本框,当失去焦点或者按下回车然后把文本框输入的值给原本的元素即可
var that;
class Tab {
constructor(id){
//获取元素
that = this;
this.main = document.querySelector(id);
this.add = this.main.querySelector('.tabadd');
//li的父元素
this.ul = this.main.querySelector('.fisrstnav ul:first-child');
//section的父元素
this.fsection = this.main.querySelector('.tabscon');
this.init();
}
init(){
this.updateNode();
//init初始化操作让相关的元素绑定事件
this.add.onclick = this.addTab;
for(var i = 0;i<this.lis.length;i++){
this.lis[i].index = i;
this.lis[i].onclick = this.taggleTab;
this.remove[i].onclick = this.removeTab;
this.spans[i].ondblclick = this.editTab;
this.sections[i].ondblclick = this.editTab;
}
}
//由于动态添加元素引起的bug,需要重新获取对应的元素
updateNode() {
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.remove = this.main.querySelectorAll('.icon-guanbi');
this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');
}
//1.切换
taggleTab(){
that.clearClass();
this.className = 'liactive';
that.sections[this.index].className = 'conactive';
}
//清除类
clearClass(){
for(var i = 0;i < this.lis.length;i++){
this.lis[i].className = '';
this.sections[i].className = '';
}
}
//2.添加
addTab(){
that.clearClass();
//创建
var random = Math.random();
var li = '<li class="liactive"><span>新的选项卡</span><span class="iconfont icon-guanbi"></span></li>'
var section = '<section class="conactive">测试 ' + random + '</section>';
//追加到父元素
that.ul.insertAdjacentHTML('beforeend',li);
that.fsection.insertAdjacentHTML('beforeend',section);
that.init();
}
//3.删除
removeTab(e) {
e.stopPropagation(); // 阻止冒泡 防止触发li 的切换点击事件
var index = this.parentNode.index;
console.log(index);
// 根据索引号删除对应的li 和section remove()方法可以直接删除指定的元素
that.lis[index].remove();
that.sections[index].remove();
that.init();
// 当我们删除的不是选中状态的li 的时候,原来的选中状态li保持不变
if (document.querySelector('.liactive')) return;
// 当我们删除了选中状态的这个li 的时候, 让它的前一个li 处于选定状态
index--;
// 手动调用我们的点击事件 不需要鼠标触发
that.lis[index] && that.lis[index].click();
}
//4.修改
editTab() {
var str = this.innerHTML;
// 双击禁止选定文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
// alert(11);
this.innerHTML = '<input type="text" />';
var input = this.children[0];
input.value = str;
input.select(); // 文本框里面的文字处于选定状态
// 当我们离开文本框就把文本框里面的值给span
input.onblur = function() {
this.parentNode.innerHTML = this.value;
};
// 按下回车也可以把文本框里面的值给span
input.onkeyup = function(e) {
if (e.keyCode === 13) {
// 手动调用表单失去焦点事件 不需要鼠标离开操作
this.blur();
}
}
}
}
new Tab('#tab');
注意:有些事件会点击子元素同时触发了父元素,产生事件冒泡,需要阻止冒泡。
\