一、常见误区
1. 数组
和php不同,在js中array是[object]类型,既然是对象,那么在函数操作里面就是地址传递
var arr = [];var run = function (a) {a.push(1);}run(arr);console.log(arr); // [1]
php数组不是对象,则函数操作是值传递,js数组是对象,则函数操作是地址传递
2. 字符串0和数字0
// 字符串0 布尔值是trueconsole.log(!!'0');// 数字0 布尔值是falseconsole.log(!!0);
在写实际业务的时候,尽量使用 if (变量>0) 代替 if (可能为0的变量)
二、高阶函数
数组的高效率方法(map, filter, forEach, reduce)
1. Array.prototype.map
用法:[].map(function(value,index,arr) { return something; });
说明: 将闭包函数应用于数组的每一个元素上,获取新的数组
参数: 数组对象map方法接收第1个参数为闭包函数,map方法结束后会返回一个新的数组,闭包函数自动接收3个参数,value为遍历的每一个数组元素,index为元素索引,arr为数组本身,闭包函数要有返回值
场景: 常用于适配。服务器返回数据库轮播图列表,而layer.photos需要元素都是图片地址字符串的数组
// 这里可能是从ajax请求服务器后得到的数据var svr_data = {att_list: [{id: 1,url: '/Public/1.jpg',},{id: 2,url: '/Public/2.jpg',}]};// 构建Layer需要的数据var data = svr_data.att_list.map(function(att_item) {return {"alt": "皇家披萨", // 图片名"pid": att_item.id, //图片id"src": 'baidu.com' + att_item.url, //原图地址"thumb": "" //缩略图地址};});// 调用layer的方法layer.photos({photos: {title: '美食图片',data: data}});// 其他场景:快速生成dom元素 ...
2. Array.prototype.filter
用法:[].filter(function(value,index,arr) { return flag; });
说明: 将闭包函数应用于数组的每一个元素上,获取过滤后的新的数组
参数: 数组对象filter方法接收第1个参数为闭包函数,filter方法结束后会返回一个新的数组,闭包函数自动接收3个参数,value为遍历的每一个数组元素,index为元素索引,arr为数组本身,闭包函数需要返回一个布尔值
场景: 常用于过滤。去掉数组某字段为空的元素
// 代码展示大概用法var odd = [1, 2, 3, 4].filter(function(n) {return n % 2;});console.log(odd); // [1, 3] 奇数数组
3. Array.prototype.forEach
用法:[].forEach(function(value,index,arr) { /* do something */ });
说明: 将闭包函数应用于数组的每一个元素上
参数: 数组对象forEach方法接收第1个参数为闭包函数,闭包函数自动接收3个参数,value为遍历的每一个数组元素,index为元素索引,arr为数组本身,闭包函数不需要返回值
场景: 简单遍历都可以替换,减少无用变量 i,j,k 等
var goods_list = [{goods_id: 1,name: '1'},{goods_id: 2,name: '2'}];goods_list.forEach(function(goods) {console.log(goods);});
4. Array.prototype.reduce
用法:[].reduce(function(p,v,i,a) { return something; }, initialValue);
说明: 将闭包函数应用于数组的每一个元素上
参数: 数组对象reduce方法接收第1个参数为闭包函数,reduce方法结束后会返回一个新的值,闭包函数自动接收4个参数,p为初始值或上一次返回值,v为元素本身,i为元素索引,a为数组本身,闭包函数需要对p进行操作后的返回值
场景: 常用于统计。如商品的价格
var goods_list = [{goods_id: 1,price: 1,num: 1},{goods_id: 2,price: 2,num: 2}];var payAmount = goods_list.reduce(function(amount, goods) {return amount + goods.price * goods.num;}, 0);console.log(payAmount); // 5
总结:map适配,filter过滤,forEach遍历,reduce统计
php 也有对应的方法 array_map, array_filter, array_reduce,用法基本相同
5. 其他函数灵活写法
// 写法1function run1(a) {return 1;}// 写法2var run2 = function(b) {return 2;};var util = {run1: run1,run2: run2,run3: function(c) {// 匿名函数return 3;}};// 闭包函数var getRun4 = function(d) {return function(e) {return d + e;};};util.run4 = getRun4(4);// 立即执行函数util.run5 = (function(f) {return function(g) {return f - g;};})(5);
为什么要用立即执行函数:https://zhuanlan.zhihu.com/p/22465092
三、ES6基础
1. 箭头函数
为了解决this问题,用箭头函数可以让代码很短,也不需要定义that, _this, self等乱七八糟的变量
// 函数缩写// ES5写法App({data: { url: 'www.baidu.com' },test: function() {console.log(this.data.url); // 正确: this 指向 appsetTimeout(function() {console.log(this.data.url); // 错误: this 指向匿名函数}, 1000);}});// ES6写法App({data: { url: 'www.baidu.com' },test() {console.log(this.data.url); // 正确: this 指向 appsetTimeout(() => { // 使用箭头console.log(this.data.url); // 正确: this 指向 app}, 1000);}});/*需要注意 onShow 的位置,如果是下面这种写法就不是预期需要的var app = {data: { url: 'www.baidu.com' },onShow: () => {console.log(this.data.url); // 报错: this 指向 windowsetTimeout(() => {console.log(this.data.url); // 报错: this 指向 window});}}...........定义函数方法...........ES5 无参数写法: function run () { return 1; }ES6 无参数写法1: const run = () => { return 1; }ES6 无参数写法2: const run = () => (1)........ES5 一参数写法: function addOne (a) { return a + 1; }ES6 一参数写法1: const addOne = (a) => { return a + 1; }ES6 一参数写法2: const addOne = a => { return a + 1; }ES6 一参数写法3: const addOne = a => (a + 1)ES6 一参数写法4: const addOne = a => a + 1........ES5 多参数写法: function add (a, b) { return a + b; }ES6 多参数写法1: const add = (a, b) => { return a + b; }ES6 多参数写法2: const add = (a, b) => (a + b)ES6 多参数写法3: const add = (a, b) => a + b*/
2. let和const
const 用于定义常量或者不可以被覆盖的对象(数组,函数,其他类型对象)
let 用于定义变量,同一作用域不可以重复定义
let和const:http://es6.ruanyifeng.com/#docs/let
3. 解构赋值
// ES5写法var value = e.detail.value;var id = e.currentTarget.dataset.id;var path = e.currentTarget.dataset.path;// ES6写法let {value} = e.detaillet {id, path} = e.currentTarget.dataset
4. 模块化
// ES5写法// utils.jsmodule.exports = {a: a, b: b};// app.jsvar util = require('./util.js'); // 只能引入全部// ES6写法// util.jsexport default {a, b}// app.jsimport util from 'util' // 引入全部import {a} from 'util' // 按需引入
5. 扩展运算符(…)
// 快速操作数组let arr = [1, 2, 3]let newArr = [0, ...arr, 4] // [0, 1, 2, 3, 4]// 小程序快速赋值// app.jsApp({globalData: {a: 1,b: 2,},getSvrData() {// ....}})// page.jsconst app = getApp();Page({data: {...app.globalData,c: 3,},...mapActions(['map', 'tel'])})
数组扩展运算符:http://es6.ruanyifeng.com/#docs/array
对象扩展运算符:http://es6.ruanyifeng.com/#docs/object
四、参考资料
- ES6入门: http://es6.ruanyifeng.com/
- ES6转ES5:https://www.babeljs.cn/repl/
