新增文章

This commit is contained in:
xugaoyi 2020-07-22 13:13:11 +08:00
parent 804d2b150d
commit c10d661b1b
4 changed files with 135 additions and 32 deletions

View File

@ -0,0 +1,102 @@
---
title: 反向拆解让人上瘾的套路,找回自律
date: 2020-07-22 13:05:49
permalink: /pages/d6d331/
categories:
- 更多
- 心情杂货
tags:
- 心理
- 自律
---
# 反向拆解让人上瘾的套路,找回自律
当你打开手机准备学习或者查个资料的时候,很有可能不知不觉的就脱离的正规... 某某app发来通知xx明星官宣啦、xx手游重磅上线一起开启修仙之旅吧 xx结衣发布新番-4k画质&AR体验、99+未读信息、支付宝到账100万元.... 你心想,就看一会,就一会儿... 不知不觉两三个小时过去了,你开始焦躁、后悔、自责。第二天,你又掉进相同的坑里。你可能会纳闷,为什么我的自制力这么差?为什么对某件事欲罢不能?
《欲罢不能-刷屏时代如何摆脱行为上瘾》一书说到:数字时代比人类历史上的任何时代都更容易上瘾...Facebook、Instagram、网络色情、网购在下钩... 问题不出在人缺乏意志力上,而在于“屏幕那边有数千人在努力工作,为的就是破坏你的自律”。
我们正在被一个算法和娱乐所包裹的电子'海洛因'中却不自知,想要摆脱这些上瘾行为,第一步就是反向拆解那些让我们上瘾的产品的套路。书中总结了六个让人上瘾的钩子:
### 1.可望不可即的诱人目标
* 色情片
* ...
### 2.无法抵挡无法预知的积极反馈
* 社交中的点赞功能
* 某音十几秒一条的视频不需要你动脑就可以轻轻松松获得哈哈大笑的快感有时候还有一种我学习到了的感觉你永远猜不到下一条将会出现什么惊喜。你刷的越多算法就越精准越知道你的情绪G点在哪里你就越容易被俘获。
* 直播中的打赏被主播表示的感谢和送上的'么么哒'
* ...
### 3.渐进式的进步和改善的感觉
* 游戏中的升级策略
* ...
### 4.随着时间的推移越来越困难的任务
* 游戏中的升级策略
* ...
### 5.需要解决却又暂未解决的紧张感
* 电影或电视剧结尾有意制造的一个悬念,给你一种未完成的紧张感,你迫切想知道后面会发生什么
* ...
### 6.强大的社会联系
* 某些游戏中能彰显地位、财富、能力等的装备(如:吃鸡游戏中的玛莎拉蒂皮肤)
* ...
## 找回自律,收获积极而长久的快乐
获得快乐的方式,你可以选择沉迷在你的手机里刷视频、打游戏、煲剧,毫不费力的收货大把的快乐。你还可以选择一条更难的路:**选择自律、选择延迟满足、选择会让你不那么舒服的努力和成长**。
收获快乐的方式没有绝对的对与错,但是,如果快乐触手可及,这种廉价的快乐也就不值得珍惜,随时都可能抛弃。过后还可能让你浪费了大把时间,该做的正事没有完成,你感觉空虚、焦躁、自责... 既然如此,我们一起选择那条更难的路吧!
::: tip 上瘾的事情收集
想想你生活中让你上瘾的事情,对照上面让人上瘾的钩子,看看是哪个钩子吧~~欢迎留言哦~
:::

View File

@ -14,9 +14,9 @@ tags:
### 基本用法
ES6 提供了新的数据结构 Set。它类似于数组但是成员的值都是唯一的没有重复的值。
ES6 提供了新的数据结构 Set。它**类似于数组,但是成员的值都是唯一的,没有重复的值**
`Set`本身是一个构造函数,用来生成 Set 数据结构。
**`Set`本身是一个构造函数,用来生成 Set 数据结构**
```javascript
const s = new Set();
@ -31,7 +31,7 @@ for (let i of s) {
<!-- more -->
上面代码通过`add()`方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。
`Set`函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
**`Set`函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化**
```javascript
// 例一
@ -57,14 +57,14 @@ set.size // 56
上面代码中,例一和例二都是`Set`函数接受数组作为参数,例三是接受类似数组的对象作为参数。
上面代码也展示了一种去除数组重复成员的方法。
上面代码也展示了一种**去除数组重复成员**的方法。
```javascript
// 去除数组的重复成员
[...new Set(array)]
```
上面的方法也可以用于,去除字符串里面的重复字符。
上面的方法也可以用于,**去除字符串里面的重复字符**
```javascript
[...new Set('ababbc')].join('')
@ -84,7 +84,7 @@ set // Set {NaN}
上面代码向 Set 实例添加了两次`NaN`,但是只会加入一个。这表明,在 Set 内部,两个`NaN`是相等的。
另外,两个对象总是不相等的。
另外,**两个对象总是不相等**的。
```javascript
let set = new Set();
@ -178,11 +178,11 @@ Set 结构的实例有四个遍历方法,可以用于遍历成员。
- `Set.prototype.entries()`:返回键值对的遍历器
- `Set.prototype.forEach()`:使用回调函数遍历每个成员
需要特别指出的是,`Set`的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。
需要特别指出的是,**`Set`的遍历顺序就是插入顺序**。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。
**1`keys()``values()``entries()`**
`keys`方法、`values`方法、`entries`方法返回的都是遍历器对象详见《Iterator 对象》一章)。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以`keys`方法和`values`方法的行为完全一致。
`keys`方法、`values`方法、`entries`方法返回的都是遍历器对象详见《Iterator 对象》一章)。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),**所以`keys`方法和`values`方法的行为完全一致**
```javascript
let set = new Set(['red', 'green', 'blue']);
@ -218,7 +218,7 @@ Set.prototype[Symbol.iterator] === Set.prototype.values
// true
```
这意味着,可以省略`values`方法,直接用`for...of`循环遍历 Set。
这意味着,可以**省略`values`方法,直接用`for...of`循环遍历 Set**
```javascript
let set = new Set(['red', 'green', 'blue']);
@ -316,9 +316,9 @@ set = new Set(Array.from(set, val => val * 2));
### 含义
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
WeakSet 结构与 Set 类似,也是**不重复的值的集合**。但是,它与 Set 有两个区别。
首先WeakSet 的成员只能是对象,而不能是其他类型的值。
首先,**WeakSet 的成员只能是对象**,而不能是其他类型的值。
```javascript
const ws = new WeakSet();
@ -330,11 +330,11 @@ ws.add(Symbol())
上面代码试图向 WeakSet 添加一个数值和`Symbol`值,结果报错,因为 WeakSet 只能放置对象。
其次WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
其次,**WeakSet 中的对象都是弱引用**,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为`0`垃圾回收机制就不会释放这块内存。结束使用该值之后有时会忘记取消引用导致内存无法释放进而可能会引发内存泄漏。WeakSet 里面的引用都不计入垃圾回收机制所以就不存在这个问题。因此WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为`0`垃圾回收机制就不会释放这块内存。结束使用该值之后有时会忘记取消引用导致内存无法释放进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,**WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息**。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
由于上面这个特点WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。
由于上面这个特点,**WeakSet 的成员是不适合引用的,因为它会随时消失**。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 **ES6 规定 WeakSet 不可遍历**
这些特点同样适用于本章后面要介绍的 WeakMap 结构。
@ -346,7 +346,7 @@ WeakSet 是一个构造函数,可以使用`new`命令,创建 WeakSet 数据
const ws = new WeakSet();
```
作为构造函数WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。
作为构造函数,**WeakSet 可以接受一个数组或类似数组的对象作为参数**。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。
```javascript
const a = [[1, 2], [3, 4]];
@ -356,7 +356,7 @@ const ws = new WeakSet(a);
上面代码中,`a`是一个数组,它有两个成员,也都是数组。将`a`作为 WeakSet 构造函数的参数,`a`的成员会自动成为 WeakSet 的成员。
注意,是`a`数组的成员成为 WeakSet 的成员,而不是`a`数组本身。这意味着,数组的成员只能是对象。
**注意,是`a`数组的成员成为 WeakSet 的成员,而不是`a`数组本身。这意味着,数组的成员只能是对象。**
```javascript
const b = [3, 4];
@ -389,7 +389,7 @@ ws.delete(window);
ws.has(window); // false
```
WeakSet 没有`size`属性,没有办法遍历它的成员。
**WeakSet 没有`size`属性**,没有办法遍历它的成员。
```javascript
ws.size // undefined
@ -437,7 +437,7 @@ data['[object HTMLDivElement]'] // "metadata"
上面代码原意是将一个 DOM 节点作为对象`data`的键,但是由于对象只接受字符串作为键名,所以`element`被自动转为字符串`[object HTMLDivElement]`。
为了解决这个问题ES6 提供了 Map 数据结构。它类似于对象也是键值对的集合但是“键”的范围不限于字符串各种类型的值包括对象都可以当作键。也就是说Object 结构提供了“字符串—值”的对应Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构Map 比 Object 更合适。
为了解决这个问题ES6 提供了 **Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键**。也就是说Object 结构提供了“字符串—值”的对应Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构Map 比 Object 更合适。
```javascript
const m = new Map();
@ -523,7 +523,7 @@ new Map().get('asfddfsasadf')
// undefined
```
注意只有对同一个对象的引用Map 结构才将其视为同一个键。这一点要非常小心。
注意,**只有对同一个对象的引用Map 结构才将其视为同一个键**。这一点要非常小心。
```javascript
const map = new Map();
@ -552,7 +552,7 @@ map.get(k2) // 222
上面代码中,变量`k1`和`k2`的值是一样的,但是它们在 Map 结构中被视为两个键。
由上可知Map 的键实际上是跟内存地址绑定的只要内存地址不一样就视为两个键。这就解决了同名属性碰撞clash的问题我们扩展别人的库的时候如果使用对象作为键名就不用担心自己的属性与原作者的属性同名。
由上可知,**Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键**。这就解决了同名属性碰撞clash的问题我们扩展别人的库的时候如果使用对象作为键名就不用担心自己的属性与原作者的属性同名。
如果 Map 的键是一个简单类型的值数字、字符串、布尔值则只要两个值严格相等Map 将其视为一个键,比如`0`和`-0`就是一个键,布尔值`true`和字符串`true`则是两个不同的键。另外,`undefined`和`null`也是两个不同的键。虽然`NaN`不严格相等于自身,但 Map 将其视为同一个键。

View File

@ -12,10 +12,11 @@ tags:
## 概述
Proxy 用于修改某些操作的默认行为等同于在语言层面做出修改所以属于一种“元编程”meta programming即对编程语言进行编程。
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“**元编程**meta programming**对编程语言进行编程**
Proxy 可以理解成在目标对象之前架设一层“拦截”外界对该对象的访问都必须先通过这层拦截因此提供了一种机制可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,**外界对该对象的访问,都必须先通过这层拦截**因此提供了一种机制可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
<!-- more -->
```javascript
var obj = new Proxy({}, {
get: function (target, propKey, receiver) {
@ -155,7 +156,7 @@ fproxy.foo === "Hello, foo" // true
### get()
`get`方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
`get`方法用于拦截某个属性的读取操作,可以接受**三个参数**,依次为**目标对象、属性名和 proxy 实例本身**(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
`get`方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子。
@ -180,7 +181,7 @@ proxy.age // 抛出一个错误
上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回`undefined`。
`get`方法可以继承
**`get`方法可以继承**
```javascript
let proto = new Proxy({}, {

View File

@ -14,9 +14,9 @@ tags:
`Reflect`对象与`Proxy`对象一样,也是 ES6 为了操作对象而提供的新 API。`Reflect`对象的设计目的有这样几个。
1 将`Object`对象的一些明显属于语言内部的方法(比如`Object.defineProperty`),放到`Reflect`对象上。现阶段,某些方法同时在`Object`和`Reflect`对象上部署,未来的新方法将只部署在`Reflect`对象上。也就是说,从`Reflect`对象上可以拿到语言内部的方法。
1 **将`Object`对象的一些明显属于语言内部的方法(比如`Object.defineProperty`),放到`Reflect`对象上。**现阶段,某些方法同时在`Object`和`Reflect`对象上部署,未来的新方法将只部署在`Reflect`对象上。也就是说,从`Reflect`对象上可以拿到语言内部的方法。
<!-- more -->
2 修改某些`Object`方法的返回结果,让其变得更合理。比如,`Object.defineProperty(obj, name, desc)`在无法定义属性时,会抛出一个错误,而`Reflect.defineProperty(obj, name, desc)`则会返回`false`。
2 **修改某些`Object`方法的返回结果,让其变得更合理**。比如,`Object.defineProperty(obj, name, desc)`在无法定义属性时,会抛出一个错误,而`Reflect.defineProperty(obj, name, desc)`则会返回`false`。
```javascript
// 老写法
@ -35,7 +35,7 @@ if (Reflect.defineProperty(target, property, attributes)) {
}
```
3 让`Object`操作都变成函数行为。某些`Object`操作是命令式,比如`name in obj`和`delete obj[name]`,而`Reflect.has(obj, name)`和`Reflect.deleteProperty(obj, name)`让它们变成了函数行为。
3 **让`Object`操作都变成函数行为**。某些`Object`操作是命令式,比如`name in obj`和`delete obj[name]`,而`Reflect.has(obj, name)`和`Reflect.deleteProperty(obj, name)`让它们变成了函数行为。
```javascript
// 老写法
@ -45,7 +45,7 @@ if (Reflect.defineProperty(target, property, attributes)) {
Reflect.has(Object, 'assign') // true
```
4`Reflect`对象的方法与`Proxy`对象的方法一一对应,只要是`Proxy`对象的方法,就能在`Reflect`对象上找到对应的方法。这就让`Proxy`对象可以方便地调用对应的`Reflect`方法,完成默认行为,作为修改行为的基础。也就是说,不管`Proxy`怎么修改默认行为,你总可以在`Reflect`上获取默认行为。
4`Reflect`对象的方法与`Proxy`对象的方法一一对应,只要是`Proxy`对象的方法,就能在`Reflect`对象上找到对应的方法。这就让`Proxy`对象可以方便地调用对应的`Reflect`方法,完成默认行为,作为修改行为的基础。也就是说,**不管`Proxy`怎么修改默认行为,你总可以在`Reflect`上获取默认行为**
```javascript
Proxy(target, {
@ -526,19 +526,19 @@ Reflect.ownKeys(myObject)
## 实例:使用 Proxy 实现观察者模式
观察者模式Observer mode指的是函数自动观察数据对象一旦对象有变化函数就会自动执行。
**观察者模式Observer mode指的是函数自动观察数据对象一旦对象有变化函数就会自动执行**
```javascript
const person = observable({
name: '张三',
age: 20
});
}); // 观察目标
function print() {
console.log(`${person.name}, ${person.age}`)
}
} // 观察者
observe(print);
observe(print); // 启动观察
person.name = '李四';
// 输出
// 李四, 20