理解JS中的迭代器和生成器

一、迭代器

在解释什么是迭代器之前先看一下下面的这段代码

var arr = [1,2,3]
for (var i = 0, len - arr.length; i < len; i++){
    console.log(arr[i])
}

这是一个非常常见的for循环,不过它存在一个问题。就是如果嵌套的过多的话,就特别容易出问题,难以维护,还有大量的重复性代码。
就像Promise为了解决回调地域一样,迭代器就是要解决这些嵌套的for循环,让代码更简洁和更容易维护。

特征:迭代器函数定义了一个next()方法,这个方法执行后会返回一个对象,拥有value和done两个属性。为了更好的理解迭代器的运行方式,我们可以自己手写一个迭代器函数,代码如下:

function createIterator (items){
    var i = 0
    return {
        next: function () {
            var done = (i >= items.length)
            var value = !done ? items[i++] : undefined
            return {
                done,
                value
            }
        }
    }
}
var iterator = createIterator([1,2,3])
console.log(iterator.next()) // {value:1, done:false}
console.log(iterator.next()) // {value:2, done:false}

我们定义了一个函数,这个函数每次执行它的next方法的时候都会返回它下次执行的时候的返回值和是否到头了。

二、生成器

如果上面的迭代器理解了,那么我们就来了解一下生成器。
定义:一句话描述生成器就是“一个能够返回一个迭代器函数的函数”。
特征:生成器函数用*function来表示,内部可以使用yield关键字。
现在把上面迭代器的那段代码现在换成生成器的方式来写:

function *createIterator(){
    yield 1
    yield 2
    yield 3
}
let iterator = createIterator()

console.log(iterator.next().value) //1
console.log(iterator.next().value) //2
console.log(iterator.next().value) //3

这样返回的结果和上面的代码一样,不过这些值都是写死的,所以我们改一下,让它能够接受参数。代码如下:

function *createIterator(items){
    for (let i = 0; i< items.length; i++){
        yield items[i]
    }
}
let iterator = createIterator([1,2,3])

console.log(iterator.next()); // { value:1, done: false }
console.log(iterator.next()); // { value:2, done: false }
console.log(iterator.next()); // { value:3, done: false }
console.log(iterator.next()); // { value:undefined, done: true }

好了,看到这里就算是基本理解了,至于一些使用的细节,比如代码格式什么的,去查文档吧。使用场景呢,需要自己去实践中练习。本文追求简单,高效的让你理解什么是迭代器和生成器,所以不能写的太详细和啰嗦,好的文章就是要“干”一点。

小程序项目采坑记录之利用try catch跟踪问题

最近忙了半年的小程序终于上线了,第一天上线就暴露出来很多问题,面对每日几万人的使用量,n种不同的终端设备,测试部门测不出来一些问题也是情有可原。
其中比较典型的一个问题就是,小程序的管理后台会报警提示我一个页面进来的参数JSON格式不正确,但是这个问题出现的几率十分不规律。1万个人里面可能也就2-3个人会出现吧。而且测试部的同事根本就不能复现出来这个bug。
因为告警只提示你摸个页面会出现JSON错误,而没有具体的Log。
困扰了很久之后,我终于想出来了一个办法,利用try chatch把报错信息捕捉到,然后把JSON对象打印到页面上面。就这样用了一个很简单的小办法就解决了这个难题,现在把这个技巧分享出来,代码如下:

 onLoad(options) {
        let that = this
        let params = {}
        let p = decodeURIComponent(options.params || '')
        try {
            params = JSON.parse(p || '{}')
        }
        catch (exception) {
            wx.showModal({
                title: '数据错误',
                content: '错误代码:' + p,
                showCancel: false,
            })
            console.log(exception)
            return
        }
        ......

通过VUE项目的proxyTable配置实现本地跨域

1. 首先我们找一个用来实验的请求地址

(如果下面这个地址访问不了,那就是距离这篇文章发表的时间过得太久导致连接已经失效。你可以随便到某个网站找一条get请求的地址):

https://shared-https.ydstatic.com/gouwuex/ext/script/load_url_s.txt

这是一个get请求,可以通过浏览器的地址栏直接访问,返回的结果是

{"src":"https://shared-https.ydstatic.com/gouwuex/ext/script/extension_3_1.js?v=1513057776750" }

Read More

h5页面js判断手机横屏

主要通过window.orientation来实现,不过这个方法貌似要被未来的标准废弃掉。
点击查看orientation文档
下面的代码最好用手机进行测试,电脑的浏览器不一定会生效。

function rotate() {
     
      if (window.orientation == 180 || window.orientation == 0) {
      alert('竖屏')
      }
      if (window.orientation == 90 || window.orientation == -90) {
      alert('横屏')
      }
    }
    window.addEventListener("load", rotate, false);
    window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", rotate, false);

JS正则表达式速成

正则表达式简介及工具

正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为”元字符”)。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

Read More

随机生成n个1-maxNum之间的值不会重复的整数组,十位补0

/**
 * 随机生成n个1-maxNum之间的值不会重复的整数组,十位补0
 * @param maxNum 1-几
 * @param n 多少个
 * @returns {arr}
 */
var randomIntNum = function(maxNum, n) {
    var oArr = [];
    var newArr = [];
    var rNum;
    for (var i = 0; i < n;) {
        rNum = parseInt(Math.random() * maxNum + 1);
        if (!oArr[rNum]) {
            oArr[rNum] = rNum;
            (rNum < 10) && (rNum = '0' + rNum);
            newArr.push(rNum);
            i++;
        }
    }
    return newArr;
}

JS数字金额大写转换

/** 数字金额大写转换(可以处理整数,小数,负数) */  
var digitUppercase = function(n) {
	var fraction = ['角', '分'];
	var digit = [
		'零', '壹', '贰', '叁', '肆',
		'伍', '陆', '柒', '捌', '玖'
	];
	var unit = [
		['元', '万', '亿'],
		['', '拾', '佰', '仟']
	];
	var head = n < 0 ? '欠' : '';
	n = Math.abs(n);
	var s = '';
	for (var i = 0; i < fraction.length; i++) {
		s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
	}
	s = s || '整';
	n = Math.floor(n);
	for (var i = 0; i < unit[0].length && n > 0; i++) {
		var p = '';
		for (var j = 0; j < unit[1].length && n > 0; j++) {
			p = digit[n % 10] + unit[1][j] + p;
			n = Math.floor(n / 10);
		}
		s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
	}
	return head + s.replace(/(零.)*零元/, '元')
		.replace(/(零.)+/g, '零')
		.replace(/^整$/, '零元整');
};

console.log(digitUppercase(12.3));

Underscore 常用方法

概述

Underscore.js是一个很精干的库,压缩后只有4KB。它提供了几十种函数式编程的方法,大大方便了Javascript的编程。MVC框架backbone.js就是基于这个库。

它定义了一个下划线(_)对象,函数库的所有方法都属于这个对象。这些方法大致上可以分成:集合(collection)、数组(array)、函数(function)、对象(object)和工具(utility)五大类。

 

在node.js下安装

Underscore.js不仅可以用于浏览器环境,还可以用于node.js。安装命令如下:

npm install underscore

但是,node.js不能直接使用_作为变量名,因此要用下面的方法使用underscore.js

var u = require("underscore");

 

与集合有关的方法

Javascript语言的数据集合,包括两种结构:数组和对象。以下的方法同时适用于这两种结构。

 

map

该方法对集合的每个成员依次进行某种操作,将返回的值依次存入一个新的数组。

_.map([1, 2, 3], function(num){ return num * 3; });  // [3, 6, 9]    _.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });  // [3, 6, 9]

 

each

该方法与map类似,依次对集合的每个成员进行某种操作,但是不返回值。

_.each([1, 2, 3], alert);    _.each({one : 1, two : 2, three : 3}, alert);

 

reduce

该方法依次对集合的每个成员进行某种操作,然后将操作结果累计在某一个初始值之上,全部操作结束之后,返回累计的值。

该方法接受三个参数。第一个参数是被处理的集合,第二个参数是对每个成员进行操作的函数,第三个参数是累计用的变量。

_.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);  // 6

reduce方法的第二个参数是操作函数,它本身又接受两个参数,第一个是累计用的变量,第二个是集合每个成员的值。
Read More