
// 1、var 声明的变量是函数级作用域 // let和const是块级作用域。(在{}内声明的变量就只能在该区域内访问。) var age=18; if(age>18){ var days=18*365; console.log(`虚度${days}天`); } days=2048;//由于var 是函数级作用域,所以在这里也能访问到。声明days的地方并不是在一个function当中。如果换成let或者const来访问,那么就会报错了。 //如果使用var 在方法中声明变量,那么该变量只能在这个方法中使用。 // 如果在函数外部声明,那么就可以当做全局变量来使用 function GetPrice () { var price=100;//若是在该函数外使用price,则会报错undefined console.log(price); } //2、使用var声明的变量可以重复定义,而使用let或const声明的变量则不可以重复定义。 var price=100; var price=200;//这里不会报错。 const discount=0.9; let name="vichin"; let name="stephen";//这里就会报错! if(discount>1){ let name="stephen";//这里就不会报错。此前的name="vichin"是全局作用域,而此处的是块级作用域。 } //当const类型的变量被赋值为一个值类型的值时,是不可以被重新赋值的。如果const类型的变量被赋值为一个引用类型的值时,是可以修改引用类型变量中的某些属性的。 const person="vichin"; person ="stephen";//这里就会报错。 const person={ name:'vichin'; age:26 }; person.age=27;//这里就不会报错。 // 如果不想让别人修改person对象中的属性,则可以使用 const vichin=Object.freeze(person); // 当我们使用var关键字声明一个name的全局变量的时候,会产生环境污染,将window自带的属性name的值也给替换掉。往常的方法是使用一个立即执行函数,然后将变量声明在这个立即执行函数当中。 // 可以使用let这个块级作用域的关键字来声明变量。 { let name="vichin"; }

//箭头函数(有点像lambda表达式) var fn=function(x){ return x * x;//ES5中的语法 } var fn2 = x => x * x;//ES6中的箭头函数。当只有一个参数传入的时候,可以省略小括号。去掉大括号,做到隐式返回。 var fun= () => {//当没有参数传入的时候,一定要写小括号。 return "vichin"; } var fun2= (x,y) => {//当传递多个参数的时候,使用逗号间隔。 return x * y; } const Jelly={ name:"jelly", hobbies:['coding','sleeping','reading'], printHobbies:function(){ this.hobbies.map(function(hobby){//这里的function是一个独立的函数,因此函数内的this并非指向Jelly这个对象,而是指向了Window。 console.log(`${this.name} love ${hobby}`);//严格模式下,这里会报错。 }) }, printLove:function(){ this.love.map(hobby=>{ console.log(`${this.name} love ${hobby}`);//这里的this就指向了Jelly这个对象。 }) } } //不适合使用箭头函数的场景 // 1、作为构造函数,一个方法需要绑定到对象 const Person=(name,points)=>{//这里使用箭头函数,函数体中的this并不会指向即将生成的对象,而是指向了window this.name=name; this.points=points; } // 1、生成一个新的对象。 // 2、将构造函数中的this指向新生成的对象。 // 3、将这个对象绑定到它的原型对象中去。 // 4、返回这个新生成的对象。 const Jelly=new Person("jelly",5); Person.prototype.updatePoints=()=>{ this.points++;//这里的this指向了父级作用域中的对象,window。 console.log(this.points); } Person.prototype.updatePoints = function(argument){ this.points++;//这里的this指向了父级作用域中的对象(Person) console.log(this.points); }; //2、当你真的需要this的时候。 const button=document.querySelector('.zoom'); button.addEventListener('click', ()=>{//如果这里不用箭头函数,那么click的回调函数会与button对象进行绑定。 this.classList.add('in');//由于使用了箭头函数,所以这里的this会是undefined。 setTime(()=>{this.classList.remove('in');},2000)//此处的this仍然指向了button对象。如果使用了function,则this会指向window。(前面有提到过) }) // 3、需要使用arguments对象 const sum = () =>{ return Array.from(arguments).reduce((prevSum,value) => prevSum + value,0) } //sum方法没有形参,所有arguments对象是不存在的。运行到Array.from(arguments)就会报错。 // Array.from会将arguments对象转化成数组

//函数中赋默认值 function multiply (a = 5,b = 3) { return a * b;//以前是a=a||5 }

//模板字符串 const person ='vichin'; const age=5; const sentence =`${person} is ${age*5} years old`;//在大括号中可以是一个变量,也可以是一个表达式或函数。 console.log(sentence); const jelly={ name:'jelly', date:'2018-11-09', todos:[ {name:'Go to Store',complete:false}, {name:'Watch Movie',complete:true}, {name:'Running',complete:true}, ] }; function RenderTodos(todos){ return (`<ul> ${todos.map(todo=>` <li> ${todo.name}${todo.complete?'√':'×'} </li> `).join('')} </ul>`); } const template=`<div class='panel'> <div class='panel-header'>${jelly.name}</div> <div class='panel-body'>${RenderTodos(jelly.todos)}</div> <div class='panel-footer'>${jelly.date}</div> </div>`;//可以使用trim将空格去掉

//标签模板字符串 function HighLight(strings,...values){//...values剩余参数。 //debugger; const highlighted=values.map(value=>`<span class='highlight'>${value}</span>`); let str=''; strings.forEach((string, i) =>str +=`${string}${highlighted[i] || ''}`); } const user='vichin'; const topic ='How to use the computer'; const sentence =HighLight`${user} don't know ${topic}`;

//对象结构 const vichin={ name:'vichin', age:25, family:{ mother:'Max V', father:'Min V', brother:'V V' }, } const {father,mother,brother}=vichin.family;//声明3个变量,并且使用family的3个属性为它们填充值。 const {name:n,age,a,money='have no money'}=vichin;//为变量name和age重命名(防止此变量在之前被声明过)

//数组结构 const numbers=['one','two','three','four']; const [one,two]=numbers; const [one,...others]=numbers;//会将数组中第一个数,放置在变量one中,其余的数会组成另一个数组。 console.log(one,ohters)//one['tow','three','four'] let a=10; let b=20; [a,b]=[b,a];//交换变量中的值

//For of loop(循环)可以用于数组,arguments对象,字符串,(nodeList)节点。 const friuts=['Apple','Banana','Orange','Mango']; friuts.forEach( friut=> { console.log(friut);//在foreach中无法使用break和continue等关键字。 }); for(let i in friuts){ console.log(friuts[i]); } //使用for……in循环,会将friuts中的所有属性都枚举出来。单纯用在数组上还行。如果用在了对象上就不行了。 //为了解决for……in的问题,可以使用for of 来解决这个问题。 for(let friut of friuts){//在for of 循环中可以使用break和continue console.log(friut[0]);//打印索引 console.log(friut[1]);//打印值 } for(let [index,friut] of friuts.entries()){ console.log(`${friut} ranks ${index+1} in my favorite friuts`); } let name='vichin'; for (let char of name){ console.log(char);//遍历字符串 }

//Array.from和 Array.of //Array.from将一个类数组对象(有length属性的)或可遍历对象(继承Iterator接口)转换成一个数组 const todos=document.querySelector('li');//获取界面上所有的li节点 const names=Array.from(todos,todo=>todo.textContent);//先将todos转换成一个Array对象,再执行后面的一个lambda表达式。 let name='vichin'; Array.form(name);//将字符串转化为一个数组。 let newAry=Array.of(1,2,3)//将1,2,3组成一个新的数组。 //Array.find(element,index,array) Array.findIndex() Array.some() Array.every() const inventory=[ {name:'apples',quantity:2}, {name:'bananas',quantity:0}, {name:'cherries',quantity:5} ]; const bananas=inventory.find(friut =>friut.name==='bananas');//返回{name:'bananas',quantity:0} const bananasIndex=inventory.findIndex(friut => friut.name==='bananas');//返回1。 const isEnough=inventory.some(friut => friut.quantity >0);//返回true。只要数组中有一个满足条件的就会返回true const isAllEnough=inventory.every(friut => friut.quantity>0);//返回false。在数组中,只要有一个不满足条件,就返回false。

function sum(...numbers){//剩余参数。(将多个参数整合成一个数组) } function sum(arguments){ } sum(1,2,3,4); function getCount(para1,...paras){ }

//spread operator intro 拓展运算符(将可遍历对象的每一个元素拓展为一个新的参数序列) const youngers=['George','John','Thomas'] const olders=['James','Wade','Mike']; //要将两个组合成一个数组,以往的操作: let members=[]; members=members.concat(youngers); members.push('Mary'); members=members.concat(olders); //在ES6中可以使用拓展运算符来解决 const members=[...youngers,'Mary',...olders]; const newAry=members; newAry[0]="vichin";//此时members中的第一个元素也会被改变。 const newAry1=[...members];//可以解决这个问题。 //拓展运算符的使用场景: //1、使用拓展运算发来替代Array.from() const todos=[...document.querySelectorAll('li')];//如果这里不用拓展运算符的话,那么就需要用Array.from() const names=todos.map(todo => todo.textContent);//这里方能使用todos.map方法。 //2、使用现有数组,创建新的数组 const ary=['Georeg','John']; const name=['vichin',...ary]; //3、删除数组中的某一项 const todos=[ {id:1,name:'Go to Store',completed:false}, {id:2,name:'Watch TV',completed:true}, {id:3,name:'Go Shopping',completed:false} ]; const id=2; const todoIndex= todos.findIndex(todo => todo.id === id); const newTodos=[...todos.slice(0,todoIndex),...todos.slice(todoIndex + 1)];//等到拼接后的新的数组,如果不加拓展运算符,那么新生成的newTodos变量只是一个对象的集合,而非数组

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> .heading span{ cursor: pointer; display:inline-block;/*span是内联元素,内联元素无法实现该动画效果*/ transition: transform 0.25;/*0.25秒的过渡时间*/ } .heading span:hover{ transform: translateY(-20px) rotate(10deg) scale(2);//Y轴移动-20px,旋转10度,放大2倍 } </style> </head> <body> <h2 class="heading"> LARAVIST! </h2> <script type="text/javascript"> const heading =document.querySelector('.heading'); heading.innerHTML=wrapWithSpan(heading.textContent); function wrapWithSpan (word) { return [...word].map(letter => `<span>${letter}</span>`).join('');//使用join方法去掉逗号 } </script> </body> </html>

//ES6中,对象字面量的改进。 const name='vichn'; const age=2; const birthday='2018-11'; //以往的写法 const person={ name:name, age:age, birthday:birthday, greet(){//省略function关键字(方法简写) alert(`Hello ${this.name}`); } }; //新的语法中(属性简写) const person={name,age,birthday}; //计算属性 let id=0; const userId={ [`user-${++id}`]:id,//user-1:1, [`user-${++id}`]:id,//user-2:2, [`user-${++id}`]:id,//user-3:3, }; const values=['vichin',26,'2018-11-25']; const vichin={ [keys.shift()]:values.shift(), [keys.shift()]:values.shift(), [keys.shift()]:values.shift(), };

//ES5中的原型继承 function Person(name,age){//构造函数 this.name=name; this.age=age; } //使用原型对象属性,新增原型对象方法。 Person.prototype.method_name = function(argument){ console.log(`Hi,I'm ${this.name}`); }; //实例化一个对象 const vichin=new Person("vichin","27"); //重写原型对象方法 Person.prototype.method_name = function(argument){ console.log(`Hi,I'm ${this.name},my age is ${this.age}`); }; //在成功的实例化一个对象之后,也可以继续为这个构造函数增加原型对象方法 Person.prototype.method_name1 = function(argument){ console.log("I'm a fan of James"); }; //在ES6中,使用class来实现原型继承。(在JS中,类是一种特殊的函数) class Person{ constructor(name,age){//类的构造函数 this.name=name; this.age=age; }//这个地方没有逗号。 info(){//定义一个方法 console.log(`Hi,I'm ${this.name},my age is ${this.age}`); } static Description(){ console.log("I'm a fan of James"); } //JS中的get,set set sex(value){ this.sex=value; } get sex(){ return `${this.sex}`; } } //使用关键字extends来继承父类Person class User extends Person{ constructor(){ super(name);// this.age; } eat(){//如果子类的方法名与父类的方法名是一样的,就会覆盖基类的方法。 console.log('have dinner') } } const vichin=new User('vichin',27);
//promise是一个对象,它能保存3种状态,pending,fulfilled和rejected。 //pending表示一个异步的操作正在进行中。 //fulfilled表示异步操作已经成功。 //rejected表示异步操作失败。 const promise = new Promise((resolve, reject) => { //创建一个promise对象 //调用resolve可以将进行中的状态变成已成功。 //reject可以将已成功的状态变成已失败。 //一旦使用了resolve或reject,那么promise的状态就被固定住,不可更改了。 //将要处理的异步代码写在promise的函数中。 wx.getSystemInfo({ success: (res) => { //在success中执行的代码表示已经执行成功。 resolve(res); //将进行中状态改成已成功。 }, fail: (err) => { reject(err); //将状态改成已失败。 } }); }); //可以随时的调用promise。来获取到异步调用的结果。 //then方法内可以传递2个回调函数: //第一个回调函数表示当promise成功后要执行的函数。 //第二个回调函数表示当promise失败后要执行的函数。 promise.then( res => console.log(res), //箭头函数的简写 err => console.log(err) ); //使用Promise来解决回调地狱的问题 const hotList = bookModel.getHotList();//hotList是一个Promise对象 hotList.then((res) => {//在第一次成功请求后台之后,再一次请求 console.log(res); return bookModel.getMyBookCount(); }).then((res)=>{//第三次请求后台API console.log(res); return bookModel.getMyBookCount(); }) const detail = bookModel.getDetail(bid);//异步请求后台1 const comments = bookModel.getComments(bid);//异步请求后台2 const likeStatus = bookModel.getLikeStatus(bid);//异步请求后台3 //Promise.all有点像C#中的Task.WhenAll方法,异步等待。(视频中说是将3个promise合并成一个promise,当3个promise方法完成后,就会执行合并后的promise中的then方法)。还有一个race(竞争)方法。 Promise.all([detail,comments,likeStatus]).then(res=>{ this.setData({ book:res[0], comments:res[1].comments, like_status :res[2].like_status, likeCount:res[2].fav_nums }); wx.hideLoading(); });