object冻结

javascript如何实现object冻结,保证一个不可变的object。

const 常量

const声明的常量的值不能通过重新赋值来改变,并且不能重新声明[声明时必须初始化]。针对的是这个变量本身,而不是变量内部的值,可直接理解为针对变量名。

1
2
3
4
5
6
7
8
9
10
11
12
13
const OBJ = {test: 123};
// 重复声明常量会报错
var OBJ;
let OBJ;
const OBJ = {test: 123}
// 给常量赋值会报错
OBJ = 'test';
// 对里面的值的操作确没有限制
OBJ.test = 1234;
Object.getOwnPropertyDescriptor(OBJ, 'test'); // {value: 1234, writable: true, enumerable: true, configurable: true}

extensible 扩展性 [Object.isExtensible, Object.preventExtensions]

如果一个对象可以添加新的属性,则这个对象是可扩展的。

1
2
3
4
5
6
7
8
9
10
11
12
13
const OBJ = {test: 123};
// 监测对象是否可扩展
Object.isExtensible(OBJ); // true
OBJ.test1 = 123; //{test: 123, test1: 123}
// 使对象不可扩展
Object.preventExtensions(OBJ);
OBJ.test2 = 123; //{test: 123, test1: 123}
Object.isExtensible(OBJ); // false
  • 不可扩展的对象的属性通常仍然可以被删除。
  • 尝试给一个不可扩展对象添加新属性的操作将会失败,不过可能是静默失败,也可能会抛出 TypeError 异常(严格模式下)。
  • Object.preventExtensions 只能阻止一个对象不能再添加新的自身属性,仍然可以为该对象的原型添加属性。

seal 密封性 [Object.isSealed, Object.seal]

密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性(enumerable)、可配置性(configurable)[属性是否可删除以及属性描述特性是否可修改]、可写性(writable),但可能可以修改已有属性的值的对象。

1
2
3
4
5
6
7
8
9
10
11
12
const OBJ = {test:123};
// 使对象不可扩展
Object.preventExtensions(OBJ);
Object.isSealed(OBJ); // false
Object.defineProperty(OBJ, "test", {configurable : false});
Object.isSealed(OBJ); // true, 也可以直接使用Object.seal(OBJ);
OBJ.test = 1234; // {test: 1234}
  • 被密封的对象,就是在不可扩展基础上讲属性描述符configurable设置为false;
  • 同时,被密封的对象,仍然有机会改变属性的值。只不过对于此对象本身而言,不可以再扩展新的属性,不可以更改已有属性的配置信息。

freeze 冻结 [Object.isFrozen, Object.freeze]

冻结(frozen)是指它不可扩展,所有属性都是不可配置的(non-configurable),且所有数据属性(data properties, 另一种是访问器属性)都是不可写的(non-writable)。

1
2
3
4
5
6
7
8
9
10
const OBJ = {test:123};
Object.freeze(OBJ);
Object.getOwnPropertyDescriptor(OBJ, 'test'); // {value: 123, writable: false, enumerable: true, configurable: false}
// 对冻结对象的任何操作都会失败
OBJ.name = "Eros"; // 改写属性值,非严格模式下静默失败;
OBJ.age = 18; // 扩展属性值,非严格模式下静默失败;
Object.defineProperty(OBJ,"test",{value: "Eros"}); // 使用defineProperty会直接报错
  • 这种层面的冻结,只是浅冻结。如果对象里面还嵌套有对象,那么这个内部对象丝毫不受影响。

递归冻结

1
2
3
4
5
6
7
8
9
10
11
Object.prototype.deepFreeze = Object.prototype.deepFreeze || function (o){
var prop, propKey;
Object.freeze(o); // 首先冻结第一层对象
for (propKey in o){
prop = o[propKey];
if(!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)){
continue;
}
deepFreeze(prop); // 递归
}
}

参考文献

ES6 CHEAT SHEET

用一页展示所有ES6(es2015)新特性——持续更新中。

let

1
2
3
4
5
{
let a = 10;
let a = 10; // 报错【重复声明报错】
}
a // ReferenceError: a is not defined【块级作用域】

const

1
2
3
4
const PI = 3.1415;
PI = 3;
PI // 3.1415 不报错,赋值会默默失败【常量】
const PI = 3.1; // TypeError: Identifier 'PI' has already been declared【重复声明报错】

参考文献

高效演讲 -- 精彩书摘

无论从事什么工作,无论在学习还是工作中,你都可能会在会议室对同事、客户讲话,也可能会在大礼堂对着几百人演讲。这样的场合,你能否抓住机会,通过演讲一举赢得支持实现梦想?
  
作者在咨询实践中,总结出了演讲中普遍适用的原则和方法,同时,科学解释了当众讲话紧张的原因,并揭示出演讲的真谛,即与听众分享。在分享精神下,紧张感会自然退去。同时,作者总结了许多行之有效的演讲方法和技巧,教你对演讲内容、风格和状态进行调整,这样,你就能通过自己的讲话吸引并打动听众,展现自己个人魅力的同时实现演讲沟通的目的。
  
当今社会,演讲已成为每个人都无法逃避的课程。通过《高效演讲:斯坦福受欢迎的沟通课》,你将学到高效演讲领域前沿的研究成果。只要运用得当,你也可以高效演讲,抓住每个讲话的机会展现自我,让成功的可能性无限增大。

environment variable

windows的环境变量的设置都应该很熟悉了,这儿不记录了,不知道的自己gg去。

换成mac后一直不太清除环境变量设置的方法和原理,此处稍作抄袭记录了。

SHELL

1
echo $SHELL

使用上面的命令可以知道使用的shell类型。
如果输出的是:csh或者是tcsh,那么你用的就是C Shell。
如果输出的是:bash,sh,zsh,那么你的用的可能就是Bourne Shell的一个变种。
Mac OS X 10.2之前默认的是C Shell。
Mac OS X 10.3之后默认的是Bourne Shell。

如果是Bourne Shell,我是这个…
那么你可以把你要添加的环境变量添加到你主目录下面的.profile或者. bash_profile,如果存在没有关系添加进去即可,如果没有生成一个。

如何配置

Mac配置环境变量的地方
1./etc/profile (建议不修改这个文件 )
全局(公有)配置,不管是哪个用户,登录时都会读取该文件。

2./etc/bashrc (一般在这个文件中添加系统级环境变量)
全局(公有)配置,bash shell执行时,不管是何种方式,都会读取此文件。

3.~/.bash_profile (一般在这个文件中添加用户级环境变量)
每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!

4.~/.bashrc
文件会在bash shell调用另一个bash shell时读取,也就是在shell中再键入bash命令启动一个新shell时就会去读该文件。这样可有效分离登录和子shell所需的环境
。但一般 来说都会在.bash_profile里调用.bashrc脚本以便统一配置用户环境。然而我用的mac并没有…

linux下环境变量用冒号隔开,所以配置的方式为:

1
export PATH=<your path>:$PATH

赠送

  • ~/.bash_logout在退出shell时被读取。所以我们可把一些清理工作的命令放到这文件中。
  • 修改host: sudo vi /etc/hosts
  • 查看系统变量用 $echo

YY

1
2
3
4
5
vim /etc/profile
# 文档末尾追加
export PATH="<your path>:$PATH"
# 想立即生效
source /etc/profile

其他常用变量通常修改~/.bash_profile

参考文献

pm2 senior (一)

搞了一周线上环境…慢慢要变成OP了…
pm2还是很好很强大的,用到的就慢慢写下来吧,当笔记了,等有空了专门研究下…像个奢望…像我这么懒的人…

内存阀值

给pm2设置一个内存阀值,若占用内存达到阀值,pm2将自动重启该服务。

1
pm2 start app.js --max-memory-restart 20M # 50K | 50M 1G

值得注意的是,这只是一种容错机制,而不能当做功能用。当你真的发现线上服务有重启现象时,就应该去挖挖自己程序的bug了。所以每次重启应该关注一下服务的重启次数额。
要生效需delete掉先前的server再start,直接restart不会生效额。

传递Node启动参数

1
pm2 start app.js --node-args="--harmony"

日志分文件

官方推荐插件pm2-logrotate,虽然star少,但它是一个独立的服务,不影响pm2运行,可以放心使用。

1
2
3
4
5
pm2 install pm2-logrotate
pm2 set pm2-logrotate:interval 1 # 默认为1,可以不设置
pm2 set pm2-logrotate:interval_unit 'DD' # 设置分文件的时间单位(默认天),DD:天;MM:月;mm:分
pm2 set pm2-logrotate:max_size 100M # 设置分文件的大小单位(默认10MB),接受G,M,K
pm2 set pm2-logrotate:retain all # 设置保存的日志数,超过将自动删除,接受 all | number

Commit message 和 Change log

此处不得不赞叹一下阮老师的文笔和高产,膜拜中…🚬
浏览过不少开源项目了,也算是github的深水用户,但还真没有太注意人家的提交注释(commit message)有什么不一样,以及每次发版时长长的chang logs。感谢小伟哥的指导,技术视野上的差距还是蛮大的,刚把得💪

先来张angular-ui-bootstrap库的commit截图
ui-bootstrap commit message

不管多少人提交代码,总是那么清晰爽快。

input-file定制样式

前端文件上传是个永恒的话题,不管是使用原先的form提交还是使用fileReader直接ajax提交Base64编码,最终的最终都离不开一个元素——input:file
这玩意长得丑不说,还在个家浏览器上长得不一样,堪称又丑又不自觉的典范。
躲是躲不掉的,那么作为一个注重美观的FE来说,改如何满足自己和客户呢?

透明配合绝对定位

使用opacity:0;使得input:file按钮处于透明状态,同时使用绝对定位使得他完全覆盖在模拟的上传按钮上。这样input:file接受click事件响应文件上传,模拟的按钮处于一层透明的薄膜下起显示作用

不兼容IE8/9/10

IE8/9/10下点击按钮的左侧类似输入框的东东无法弹出文件选择框,并且会出现光标…
因为input:file包括一个文本区域和一个浏览按钮,,在IE8/9/10中点击文本区域,是不会弹出文件选择框的,并且在所有的IE版本中即使将它设置为透明,依然会有光标的出现。

解决方案:使用font-size属性把input:file的浏览按钮撑得足够大以至于完全覆盖显示区域

simple stress testing tool

介绍两款简单的压力测试软件webbenchsiege,使用起来都非常方便。

siege

这还是2BB的找了半天,然后在自己机器上编译安装的产物…结果后来发现mac自带webbenc,欲哭无泪啊。

安装

1
2
3
4
5
curl -O http://download.joedog.org/siege/siege-latest.tar.gz
tar -zxvf siege-latest.tar.gz
cd siege-*
./configure
make && make install

使用实例

1
2
siege -c 10 -t 10M https://www.baidu.com # 并发数10持续时间10min的请求百度
siege -t 100s -f url.txt # 持续请求url.txt中的url列表100s,每次取一个url

参数详解

1
2
3
4
5
6
7
8
9
10
11
12
13
-C | –config # 在屏幕上打印显示出当前的配置,配置是包括在他的配置文件$HOME/.siegerc中
# 可以编辑里面的参数,这样每次siege 都会按照它运行
-v # 运行时能看到详细的运行信息
-c n | –concurrent=n # 模拟有n个用户在同时访问,n不要设得太大,因为越大,siege 消耗本地机器的资源越多
-i | –internet # 随机访问urls.txt中的url列表项,以此模拟真实的访问情况(随机性),当urls.txt存在是有效
-d n | –delay=n # hit每个url之间的延迟,在0-n之间
-r n | –reps=n # 重复运行测试n次,不能与 -t同时存在
-t n | –time=n # 持续运行siege ‘n’秒(如10S),分钟(10M),小时(10H)
-l # 运行结束,将统计数据保存到日志文件中siege.log
# 一般位于/usr/local/var/siege .log中,也可在.siegerc中自定义
-R SIEGERC | –rc=SIEGERC # 指定用特定的siege 配置文件来运行,默认的为$HOME/.siegerc
-f FILE | –file=FILE # 指定用特定的urls文件运行siege ,默认为urls.txt,位于siege 安装目录下的etc/urls.txt
-u URL | –url=URL # 测试指定的一个URL,对它进行”siege “,此选项会忽略有关urls文件的设定