var、let、const区别

 javascript  var、let、const区别已关闭评论
2月 182019
 

var、let、const区别

在javascript中有三种声明变量的方式:var、let、const。

var 声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循环同样可以使用。

for(var i=0;i<=1000;i++){ 
var sum=0; 
sum+=i; 

alert(sum);

声明在for循环内部的sum,跳出for循环一样可以使用,不会报错正常弹出结果

 

let:声明块级变量,即局部变量。 

在上面的例子中,跳出for循环,再使用sum变量就会报错,有着严格的作用域,变量只作用域当前隶属的代码块,不可重复定义同一个变量,不可在声明之前调用,必须先定义再使用,会报错,循环体中可以用let

注意:必须声明’use strict’;后才能使用let声明变量否则浏览并不能显示结果,

 

const:用于声明常量,也具有块级作用域 ,也可声明块级。

const PI=3.14;

它和let一样,也不能重复定义同一个变量,const一旦定义,无法修改

产生Ethereum HD wallet代码,BIP32、BIP39、BIP44, 使用javascript套件产生Ethereum HD Wallet

 区块链  产生Ethereum HD wallet代码,BIP32、BIP39、BIP44, 使用javascript套件产生Ethereum HD Wallet已关闭评论
11月 012018
 

非常好的文章,来自: https://www.jianshu.com/p/30af695404b0

钱包是很多人第一次接触 Ethereum 或其他虚拟货币的地方。不管是用手机或浏览器的钱包,相信很多人都对一串陌生的单字感到好奇(而且很重要还要备份)。这是源自于 Bitcoin 中钱包的设计,采用这套机制的钱包通常称为 HD Wallet本篇希望简述 HD Wallet 的架构,再使用 JavaScript 套件从头创建一个 Ethereum HD Wallet

虚拟货币钱包

钱包顾名思义是存放$$$。但在虚拟货币世界有点不一样,我的帐户资讯(像是我有多少钱)是储存在区块链上,实际存在钱包中的是我的帐户对应的 key。有了这把 key 我就可以在虚拟货币世界证明我的身份、就可以更改我帐户的状态(像是送钱给别人)。这样来说,虚拟货币钱包实际上是管理和储存 key 的工具。这把 key 就是我的私钥,而帐户是从我的公钥衍伸出来。

Ledger 虚拟货币钱包

BIP32, BIP39, BIP44

BIP 全名是 Bitcoin Improvement Proposals,是提出 Bitcoin 的新功能或改进措施的文件。可由任何人提出,经过审核后公布在 bitcoin/bips 上。BIP 和 Bitcoin 的关系,就像是 RFC 之于 Internet。

而其中的 BIP32, BIP39, BIP44 共同定义了目前被广泛使用的 HD Wallet,包含其设计动机和理念、实作方式、实例等。

  • BIP32:定义 Hierarchical Deterministic wallet (简称 “HD Wallet”),是一个系统可以从单一个 seed 产生一树状结构储存多组 keypairs(私钥和公钥)。好处是可以方便的备份、转移到其他相容装置(因为都只需要 seed),以及分层的权限控制等。

BIP32 定义的 HD Wallet

  • BIP39:将 seed 用方便记忆和书写的单字表示。一般由 12 个单字组成,称为 mnemonic code(phrase),中文称为助记词或助记码。例如:

    rose rocket invest real refuse margin festival danger anger border idle brown

  • BIP44:基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。各层定义如下:

    m / purpose’ / coin_type’ / account’ / change / address_index

    其中的purporse’固定是44’,代表使用 BIP44。而coin_type’用来表示不同币种,例如 Bitcoin 就是0’,Ethereum 是60’。

Ethereum HD Wallet

Ethereum 的钱包目前均采用以上 Bitcoin HD Wallet 的架构,并订coin_type’为60’,可以在 ethereum/EIPs/issues 中看到相关的讨论。举例来说,在一个 Ethereum HD Wallet 中,第一个帐户(这里的帐户指 BIP44 中定义的account’)的第一组 keypair,其路径会是m/44’/60’/0’/0/0。


创建 Ethereum HD wallet

使用的 JavaScript 套件包含:

  • bip39:实作 BIP39,随机产生新的 mnemonic code,并可以将其转成 binary 的 seed。
  • ethereumjs-wallet:产生和管理公私钥,我使用其中的 hdkey 子套件来创建 HD Wallet。
  • ethereumjs-util:集合许多 Ethereum 需要的运算功能。

安装套件

npm install bip39 ethereumjs-wallet ethereumjs-util --save

汇入套件

var bip39 = require('bip39') var hdkey = require('ethereumjs-wallet/hdkey') var util = require('ethereumjs-util')

产生 mnemonic code

var mnemonic = bip39.generateMnemonic()

取得的 mnemonic code 会像:

rose rocket invest real refuse margin festival danger anger border idle brown

产生 HD wallet

先将 mnemonic code 转成 binary 的 seed。

var seed = bip39.mnemonicToSeed(mnemonic)

使用 seed 产生 HD Wallet。如果要说更明确,就是产生 Master Key 并记录起来。

var hdWallet = hdkey.fromMasterSeed(seed)

产生第一个 Ethereum Address

产生 Wallet 中第一个帐户的第一组 keypair。可以从 Master Key,根据其路径m/44’/60’/0’/0/0推导出来。

var key1 = hdWallet.derivePath("m/44'/60'/0'/0/0")

使用 keypair 中的公钥产生 address。

var address1 = util.pubToAddress(key1._hdkey._publicKey, true)

取得的 Address:

685ce4cbdd5c19b64ca008cb85b83947e5318efa

Encoding Address

Ethereum 很贴心,为了避免大家打错 address(导致把钱送错人),Ethereum 让 Address 变得比较难打?!总之一般会用 EIP55: Mixed-case checksum address encoding 再进行编码。许多钱包也支援用户输入没经过编码的 Address,那就会跳过 checksum 机制,建议还是使用编码过的 Address。

address1 = util.toChecksumAddress(address1.toString('hex'))

最后取得的 Address 会像:

0x685ce4CbDd5c19b64CA008cB85b83947e5318EFA

可以用 Mnemonic Code Converter 验证结果

输入 mnemonic code

产生 Address、公钥、私钥,结果和我取得的 Address 一致


使用 Ethereum HD wallet

把 mnemonic code 记录下来好好保存,就会是一个冷钱包(指不连网路的钱包,所以安全很多)。可以使用产生出来的 address 收 Ether 或任何 REC20 Token。要送钱的话,可以汇入到任一个支援 Ethereum HD Wallet 的钱包。常用的 Ethereum HD wallet 像,在浏览器使用的 MyEtherWallet、MetaMask 和在手机使用的 imToken 等。

MetaMask

题外话,MetaMask 如何在浏览器储存我们的 mnemonic code?

相信大家都了解了,有 mnemonic code 就可以产生 HD Wallet 中所有的 keys。有了 keys 就可以任意送钱包中的 Ether 或 Token 给别人。所以 mnemonic code 很重要!!!那这么重要的东西保存在浏览器不会很危险吗?我便研究下我常用的 MetaMask 浏览器钱包。MetaMask 将加密后的 mnemonic code 存在浏览器的 Local Storage(一块只存在 Local 且不会过期的资料区块)。加密使用用户另外输入的密码,再汇入时会要求用户设定密码(如上图),而每一次重新开启钱包都会要求输入密码。解密算法有 Open Source,也有线上 Live Demo

MetaMask Local Storage


References

其他相关 Ethereum JavaScript 套件

作者:安德森_Anderson
链接:https://www.jianshu.com/p/54a2b14dfdf2
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

详解JS正则replace的使用方法

 javascript  详解JS正则replace的使用方法已关闭评论
2月 092018
 

想不到一个replace还有这么多奥妙:http://www.jb51.net/article/80544.htm 

在讲replace的高级应用之前,我们先简单梳理一下JS正则中的几个重要的知识点,以帮助你对基础知识的回顾,然后再讲解JS正则表达式在replace中的使用,以及常见的几个经典案例。 

一、正则表达式的创建

JS正则的创建有两种方式: new RegExp() 和 直接字面量。

?
1
2
3
4
5
//使用RegExp对象创建
varregObj =newRegExp(“(^\s+)|(\s+$)”,”g”);
 
//使用直接字面量创建
varregStr = /(^\s+)|(\s+$)/g;

其中 g 表示全文匹配,与之相关的还有 i 和m,i 表示匹配时忽略大小写,m 表示多行匹配,如果多个条件同时使用时,则写成:gmi 

二、()、[]、{} 的区别

() 的作用是提取匹配的字符串。表达式中有几个()就会得到几个相应的匹配字符串。比如 (\s+) 表示连续空格的字符串。

[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示字符文本要匹配英文字符和数字。

{}一般用来表示匹配的长度,比如 \d{3} 表示匹配三个空格,\d[1,3]表示匹配1~3个空格。

三、^ 和 $

^ 匹配一个字符串的开头,比如 (^a) 就是匹配以字母a开头的字符串

$ 匹配一个字符串的结尾,比如 (b$) 就是匹配以字母b结尾的字符串

^ 还有另个一个作用就是取反,比如[^xyz] 表示匹配的字符串不包含xyz

需要注意的是:如果^出现在[]中一般表示取反,而出现在其他地方则是匹配字符串的开头

四、\d  \s  \w  .

\d 匹配一个非负整数, 等价于 [0-9]

\s 匹配一个空白字符

\w 匹配一个英文字母或数字,等价于[0-9a-zA-Z]

.   匹配除换行符以外的任意字符,等价于[^\n]

五、* + ?

* 表示匹配前面元素0次或多次,比如 (\s*) 就是匹配0个或多个空格

+ 表示匹配前面元素1次或多次,比如 (\d+) 就是匹配由至少1个整数组成的字符串

? 表示匹配前面元素0次或1次,相当于{0,1} ,比如(\w?) 就是匹配最多由1个字母或数字组成的字符串

六、test 、match

前面的大都是JS正则表达式的语法,而test则是用来检测字符串是否匹配某一个正则表达式,如果匹配就会返回true,反之则返回false

?
1
2
3
/\d+/.test(“123”) ;//true
 
/\d+/.test(“abc”) ;//false

match是获取正则匹配到的结果,以数组的形式返回

“186a619b28”.match(/\d+/g); // [“186″,”619″,”28”] 

以上基本上是我经常用到的基础知识,不是很全面,不常用的就没有列出来,因为列出来也只是摆设,反而混淆主次!

七、replace

replace 本身是JavaScript字符串对象的一个方法,它允许接收两个参数:

replace([RegExp|String],[String|Function])
第1个参数可以是一个普通的字符串或是一个正则表达式

第2个参数可以是一个普通的字符串或是一个回调函数

如果第1个参数是RegExp, JS会先提取RegExp匹配出的结果,然后用第2个参数逐一替换匹配出的结果

如果第2个参数是回调函数,每匹配到一个结果就回调一次,每次回调都会传递以下参数:

?
1
2
3
4
5
6
7
result: 本次匹配到的结果
 
$1,…$9: 正则表达式中有几个(),就会传递几个参数,$1~$9分别代表本次匹配中每个()提取的结果,最多9个
 
offset:记录本次匹配的开始位置
 
source:接受匹配的原始字符串

以下是replace和JS正则搭配使用的几个常见经典案例: 

(1)实现字符串的trim函数,去除字符串两边的空格

?
1
2
3
4
5
6
7
8
9
10
String.prototype.trim =function(){
 
  //方式一:将匹配到的每一个结果都用””替换
  returnthis.replace(/(^\s+)|(\s+$)/g,function(){
    return””;
  });
 
  //方式二:和方式一的原理相同
  returnthis.replace(/(^\s+)|(\s+$)/g,”);
};

^\s+ 表示以空格开头的连续空白字符,\s+$ 表示以空格结尾的连续空白字符,加上() 就是将匹配到的结果提取出来,由于是 | 的关系,因此这个表达式最多会match到两个结果集,然后执行两次替换:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String.prototype.trim =function(){
  /**
   * @param rs:匹配结果
   * @param $1:第1个()提取结果
   * @param $2:第2个()提取结果
   * @param offset:匹配开始位置
   * @param source:原始字符串
   */
  this.replace(/(^\s+)|(\s+$)/g,function(rs,$1,$2,offset,source){
    //arguments中的每个元素对应一个参数
    console.log(arguments);
  });
};
 
” abcd “.trim();
 
输出结果:
 
[” “,” “, undefined, 0,” abcd “]//第1次匹配结果
[” “, undefined,” “, 5,” abcd “]//第2次匹配结果

(2)提取浏览器url中的参数名和参数值,生成一个key/value的对象

?
1
2
3
4
5
6
7
8
9
10
11
functiongetUrlParamObj(){
  varobj = {};
  //获取url的参数部分
  varparams = window.location.search.substr(1);
  //[^&=]+ 表示不含&或=的连续字符,加上()就是提取对应字符串
  params.replace(/([^&=]+)=([^&=]*)/gi,function(rs,$1,$2){
    obj[$1] = $2;
  });
 
  returnobj;
}

/([^&=]+)=([^&=]*)/gi 每次匹配到的都是一个完整key/value,形如 xxxx=xxx, 每当匹配到一个这样的结果时就执行回调,并传递匹配到的key和value,对应到$1和$2

(3)在字符串指定位置插入新字符串

?
1
2
3
4
5
6
7
8
9
10
String.prototype.insetAt =function(str,offset){
 
  //使用RegExp()构造函数创建正则表达式
  varregx =newRegExp(“(.{“+offset+”})”);
 
  returnthis.replace(regx,”$1″+str);
};
 
“abcd”.insetAt(‘xyz’,2);//在b和c之间插入xyz
>>”abxyzcd”

当offset=2时,正则表达式为:(^.{2})  .表示除\n之外的任意字符,后面加{2} 就是匹配以数字或字母组成的前两个连续字符,加()就会将匹配到的结果提取出来,然后通过replace将匹配到的结果替换为新的字符串,形如:结果=结果+str

(4) 将手机号12988886666转化成129 8888 6666

?
1
2
3
4
5
6
7
8
9
10
11
12
functiontelFormat(tel){
 
  tel = String(tel);
 
  //方式一
  returntel.replace(/(\d{3})(\d{4})(\d{4})/,function(rs,$1,$2,$3){
    return$1+” “+$2+” “+$3
  });
 
  //方式二
  returntel.replace(/(\d{3})(\d{4})(\d{4})/,”$1 $2 $3″);
}

(\d{3}\d{4}\d{4}) 可以匹配完整的手机号,并分别提取前3位、4-7位和8-11位,”$1 $2 $3″ 是在三个结果集中间加空格组成新的字符串,然后替换完整的手机号。

 (5) 实现函数escapeHtml,将<, >, &, ” 进行转义

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
functionescapeHtml(str) {
  //匹配< > ” &
  returnstr.replace(/[<>”&]/g,function(rs) {
    switch(rs) {
      case”<“:
        return”<“;
      case”>”:
        return”>”;
      case”&”:
        return”&”;
      case”\””:
        return”””;
    }
  });
}