学习了很多vue的视频,还有nuxt的,还是不会。
还是要学ES6
本文的大部分出自小马老师的资料,还有曾大佬的文章
变量(Let 和 const)
在es6中,多用let 和const 来声明变量类型。因为var 会提前声明,也就是说,在spcrit标签中,每当检查到var 修饰的变量,就会把这个变量提前到scprit标签的第一行去自动声明后再用。这可能会导致var 变量的值出现变化。
例如:
输出结果是10,不是5
let 和const 的优点:
01.没有变量提升,像java代码顺序执行
02.是个块级变量,出了作用域就无法找到相关用let 或者 const修饰的变量
03.不能重复声明(这里是不允许在相同作用域内,此外,用const修饰的变量,不能重复赋值)
模块化字符串:就是用${变量名},来去获取变量
querySelector() 的用法:
querySelector() 方法仅仅返回匹配指定选择器的第一个元素。
解构赋值:
解构赋值是对赋值运算符的一种扩展。它通常针对数组和对象进行操作。
01.数组解构(左边是声明的数组,右边也是一个数组)
之前的赋值类似于编程语句,就好像:
let a = 1;
let b = 2;
let c = 3;
在es6中:
let [a,b,c] = [1,2,3];
数组中的a=1,b=2,c=3
let [foo] = [];
let [bar, foo] = [1];
这里的foo=空值,也就是undefined
第二个数组中,只有bar被赋值,bar=1,foo并又没被赋值,foo=空值,也是undefined
02.对象解构(左边是声明的有{}来包裹,右边是对象名,或者也是用{}来包裹)
解构可以用于对象
let node = {
type:'identifier',
name:'foo'
}
let {type,name} = node;
console.log(type,name)//identifier foo
其中,第二段代码let {type,name} = node; 中的type和name是必须和对象的属性名一样才可以。如果对象的属性名改了,第二段代码中的字段也要相应的发生改变。
用剩余运算符:
let obj = {
a:{
name:'张三'
},
b:[],
c:'hello world'
}
//可忽略 忽略b,c属性
let {a} = obj;
//剩余运算符 使用此法将其它属性展开到一个对象中存储
let {a,...res} = obj;
console.log(a,res);
比如说这个对象obj,有三个属性,一个是a,一个是数组b,一个是字符串c,
第二段代码let {a} = obj,只是将obj中的a赋值给了a,其他的并没有赋值
用剩余运算符…变量名,这样的话,就会把obj对象的除了a以外的参数,分割成一个个的对象赋值给一个数组,这个数组的名字叫做变量名,这里也就是res。
默认赋值:
let {a,b = 10} = {a:20};
b的默认赋值是10,如果没有对b进行赋值的话,b就会用默认值。
函数参数解构赋值:
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
这里的参数是一个数组,直接用一个数组来实例化参数
function addCart(n,num=0){
return n+num;
}
addCart(10);//10
addCart(10,20); //30
这里用默认值,用一个参数,那个用默认值的参数会用默认值来赋值。也可以都赋值。
函数的扩展:
在之前的es5中,函数参数不能直接为函数的参数指定默认值,只能采用变通的方法
function log(x,y){
y = y || 'world';
console.log(x,y);
}
log('hello');//hello world
log('hello','china') //hello china
log('hello','')//hello world
js中的逻辑运算符:
js中的或运算||
let 变量 = 表达式1 || 表达式2
运算逻辑如下:
第 1 步:计算第一个操作数(左侧的表达式1)的值。
第 2 步:检测第一个操作数的值。如果左侧表达式的值可转换为 true,那么就会结束运算,直接返回第一个操作数的值。(没有赋值的表达式默认是false)
第 3 步:如果第一个操作数可以转换为 false,则计算第二个操作数(右侧的表达式2)的值。
第 4 步:返回第二个操作数的值。
总结是:或运算就是左边的是真的话,返回左边的表达式,如果左边的是假的话,返回右边的表达式
js中的与运算&&
let 变量 = 表达式1 && 表达式2
运算逻辑如下:
第 1 步:计算第一个操作数(左侧表达式)的值。
第 2 步:检测第一个操作数的值。如果左侧表达式的值可转换为 false(如 null、undefined、NaN、0、“”、false),那么就会结束运算,直接返回第一个操作数的值。
第 3 步:如果第一个操作数可以转换为 true,则计算第二个操作数(右侧表达式)的值。
第 4 步:返回第二个操作数的值。
总结是:左边的是真的话,返回右边的表达式,如果左边是假的话,返回左边的表达式
(也就是运算结果的真假,左边是真的,那结果取决于右边的表达式,直接返回右边的表达式即可;左边的表达式也就是假的话,结果一定是假,那么直接返回左边的表达式即可)
es6中:采用直接默认赋值的方法,即直接写在参数定义的后面。
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
默认的参数赋值可以是一个函数来赋值:
function getVal(val) {
return val + 5;
}
function add2(a, b = getVal(5)) {
return a + b;
}
console.log(add2(10));//20
rest参数:
ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
上面代码的add函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。
箭头函数
ES6允许使用箭头=>定义函数
let f = v=>v;
//等同于
let f = function(v){
return v;
}
// 有一个参数
let add = value => value;
//等同于
let add = function(value ){
return value ;
}
// 有两个参数
let add = (value,value2) => value + value2;
let add = (value1,value2)=>{
return value1 + value2;
}
//等同于
let add = function(value1,value2 ){
return value1 + value2;
}
// 无参数
let fn = () => "hello world";
//等同于
let add = function(){
return "hello world";
}
//如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
let getId = id => ({id: id,name: 'mjj'}) //注意
let obj = getId(1);
//等同于
let add = function(id){
return {
id:‘id’ ,
name:‘mjj’
}
}
使用注意点:
没有this绑定
let PageHandler = {
id:123,
init:function(){
document.addEventListener('click',function(event) {
this.doSomeThings(event.type);
},false);
},
doSomeThings:function(type){
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandler.init();
//解决this指向问题
let PageHandler = {
id: 123,
init: function () {
// 使用bind来改变内部函数this的指向
document.addEventListener('click', function (event) {
this.doSomeThings(event.type);
}.bind(this), false);
},
doSomeThings: function (type) {
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandler.init();
let PageHandler = {
id: 123,
init: function () {
// 箭头函数没有this的指向,箭头函数内部的this值只能通过查找作用域链来确定
// 如果箭头函数被一个非箭头函数所包括,那么这里的this的值与该非箭头函数的所属对象相等,否则 则是全局的window对象
document.addEventListener('click', (event) => {
console.log(this);
this.doSomeThings(event.type);
}, false);
},
doSomeThings: function (type) {
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandler.init();
注解:
bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值(每一个函数都有一个this属性,指向这个方法所属的对象)会被绑定到传入bind()中的第一个参数的值,表示是这个对象调用了这个函数,例如:f.bind(obj),实际上可以理解为obj.f(),这时f函数体内的this自然指向的是obj;
例如:执行以下的代码
var a = {
b: function() {
var func = function() {
console.log(this.c);
}
func();
},
c: 'hello'
}
a.b();
console.log(a.c);
那么答案是什么呢?undefined和hello,大家可以打印看下,这个就是因为fun()这个函数执行的时候他的函数上下文为window,而a.b()的这个函数的执行的时候函数上下文this为a对象是什么意思呢?
var a = {
b: function() {
console.log(this.c); //hello
var func = function() {
console.log(this.c); //undefined
}
func();
},
c: 'hello'
}
a.b();
当我们希望func()他的输出的值就是为hrllo怎么办
方法一:改变this的值
var a = {
b: function() {
var _this = this; // 通过赋值的方式将this赋值给that
var func = function() {
console.log(_this.c);
}
func();
},
c: 'hello'
}
a.b(); // hello
console.log(a.c); // hello
方法二:绑定this的值发生改变
/ 使用bind方法一
var a = {
b: function() {
var func = function() {
console.log(this.c);
}.bind(this);
func();
},
c: 'hello'
}
a.b(); // hello
console.log(a.c); // hello
这里我们以a.b()的形式去执行a对象中的b这个函数,是经过对象a的所以当我们来执行a对象中b函数的时候找this就会先找到a对象所以在a对象中的b这个函数中的this为a对象,所以这个时候bind,绑定的this也就是为a对象了。
这里的Person先是采用了无参数的函数,返回是一个空的对象。
对象的扩展
属性的简洁表示法
const name = '张三';
const age = 19;
const person = {
name, //等同于name:name
age,//等同于age:age,前一个是对象person的属性,后一个是之前声明的变量 const age
// 方法也可以简写
sayName() {
console.log(this.name);
}
}
person.sayName();
这种写法用于函数的返回值,将会非常方便。
function getPoint() {
const x = 1;
const y = 10;
return {x, y};
}
getPoint()
// {x:1, y:10}
对象扩展运算符
const [a, ...b] = [1, 2, 3];
a // 1
b // [2, 3]
解构赋值
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
注意:解构赋值必须是最后一个参数,否则会报错
扩展运算符
对象的扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
Promise(我的想法是类似于ajax的异步通信)
Promise 是异步编程的一种解决方案:
从语法上讲,Promise是一个对象,通过它可以获取异步操作的消息;
从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
promise有三种状态:pending(等待态),fulfilled(成功态),rejected(失败态);
状态一旦改变,就不会再变。
创造promise实例后,它会立即执行。
Class的基本用法
简介
JavaScript语言中,生成实例对象的传统方法是通过构造函数
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
return this.sayName;
}
let p = new Person('小马哥',18);
console.log(p);
上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样
javascript复制代码
class Person {
// constructor方法 是类的默认方法,通过new命令生成对象实例时,自动调用该方法,一个类必须有constructor方法,如果没有定义,会被默认添加
constructor(name, age) {
this.name = name;
this.age = age;
}
//等同于Person.prototype = function sayName(){}
sayName(){
return this.name;
}
}
console.log(Person===Person.prototype.constructor)
类的方法内部如果含有this,它默认指向类的实例