-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
577 lines (309 loc) · 255 KB
/
atom.xml
File metadata and controls
577 lines (309 loc) · 255 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Yanng</title>
<link href="/atom.xml" rel="self"/>
<link href="https://blog.yanng.io/"/>
<updated>2019-02-27T15:35:35.000Z</updated>
<id>https://blog.yanng.io/</id>
<author>
<name>Yanng</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>webpack:从入门到真实项目配置</title>
<link href="https://blog.yanng.io/2019/01/21/webpack%EF%BC%9A%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%9C%9F%E5%AE%9E%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE/"/>
<id>https://blog.yanng.io/2019/01/21/webpack%EF%BC%9A%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%9C%9F%E5%AE%9E%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE/</id>
<published>2019-01-21T14:43:57.000Z</published>
<updated>2019-02-27T15:35:35.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>该文使用的 Webpack 版本为 3.6.0,本文分两部分。第一步是简单的使用 webpack,第二部分通过一个真实项目来配置 webpack,没有使用任何的 CLI,都是一步步配置直到完成生产代码的打包。这是本项目对应的仓库,每个小节基本都对应了一次 commit。</p></blockquote><p>这是本文的大纲,如果觉得有兴趣你就可以往下看了</p><p><img src="-88535653-1329-4dfb-b981-949231628066aee41c18f38e99efaa09c7691ac7da4f" alt=""></p><h2 id="Webpack-到底是什么"><a href="#Webpack-到底是什么" class="headerlink" title="Webpack 到底是什么"></a>Webpack 到底是什么</h2><p>自从出现模块化以后,大家可以将原本一坨代码分离到个个模块中,但是由此引发了一个问题。每个 JS 文件都需要从服务器去拿,由此会导致加载速度变慢。Webpack 最主要的目的就是为了解决这个问题,将所有小文件打包成一个或多个大文件,官网的图片很好的诠释了这个事情,除此之外,Webpack 也是一个能让你使用各种前端新技术的工具。</p><p><img src="-b9356168-23ab-4784-8c6b-be89959ee41f92a95decddcecb9e25304f3b6a9dfb9c" alt=""></p><h2 id="简单使用"><a href="#简单使用" class="headerlink" title="简单使用"></a>简单使用</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>在命令行中依次输入</p><pre><code>mkdir webpack-democd webpack-demo// 创建 package.json,这里会问一些问题,直接回车跳过就行npm init// 推荐这个安装方式,当然你也安装在全局环境下// 这种安装方式会将 webpack 放入 devDependencies 依赖中npm install --save-dev webpack</code></pre><p>然后按照下图创建文件</p><p><img src="-7db72335-3e75-48bb-9ba2-6ff9a1fc13715c88d60a69942526609db63c7919ddaf" alt=""></p><p>在以下文件写入代码</p><pre><code>// sum.js// 这个模块化写法是 node 环境独有的,浏览器原生不支持使用module.exports = function(a, b) { return a + b}// index.jsvar sum = require('./sum')console.log(sum(1, 2))<!DOCTYPE html><html lang="en"> <head> <title>Document</title> </head> <body> <div id="app"></div> <script src="./build/bundle.js"></script> </body></html></code></pre><p>现在我们开始配置最简单的 webpack,首先创建 <code>webpack.config.js</code> 文件,然后写入如下代码</p><pre><code>// 自带的库const path = require('path')module.exports = { entry: './app/index.js', // 入口文件 output: { path: path.resolve(__dirname, 'build'), // 必须使用绝对地址,输出文件夹 filename: 'bundle.js', // 打包后输出文件的文件名 },}</code></pre><p>现在我们可以开始使用 webpack 了,在命令行中输入</p><pre><code>node_modules/.bin/webpack</code></pre><p>没问题的话你应该可以看到类似的样子</p><p><img src="-e26df332-a56d-47d3-89f6-594e1d3a370ca0c2767b86d0b34f3bf66225377d4663" alt=""></p><p>可以发现原本两个 JS 文件只有 100B,但是打包后却增长到 2.66KB,这之中 webpack 肯定做了什么事情,我们去 <code>bundle.js</code> 文件中看看。</p><p>把代码简化以后,核心思路是这样的</p><pre><code>var array = [ function() { var sum = array[1] console.log(sum(1, 2)) }, function(a, b) { return a + b },]array[0]() // -> 3</code></pre><p>因为 <code>module.export</code> 浏览器是不支持的,所以 webpack 将代码改成浏览器能识别的样子。现在将 <code>index.html</code> 文件在浏览器中打开,应该也可以看到正确的 log。</p><p>我们之前是在文件夹中安装的 webpack,每次要输入 <code>node_modules/.bin/webpack</code> 过于繁琐,可以在 <code>package.json</code> 如下修改</p><pre><code>"scripts": { "start": "webpack" },</code></pre><p>然后再次执行 <code>npm run start</code>,可以发现和之前的效果是相同的。简单的使用到此为止,接下来我们来探索 webpack 更多的功能。</p><h2 id="Loader"><a href="#Loader" class="headerlink" title="Loader"></a>Loader</h2><p>Loader 是 webpack 一个很强大功能,这个功能可以让你使用很多新的技术。</p><h3 id="Babel"><a href="#Babel" class="headerlink" title="Babel"></a>Babel</h3><p>Babel 可以让你使用 ES2015/16/17 写代码而不用顾忌浏览器的问题,Babel 可以帮你转换代码。首先安装必要的几个 Babel 库</p><pre><code>npm i --save-dev babel-loader babel-core babel-preset-env</code></pre><p>先介绍下我们安装的三个库</p><ul><li>babel-loader 用于让 webpack 知道如何运行 babel</li><li>babel-core 可以看做编译器,这个库知道如何解析代码</li><li>babel-preset-env 这个库可以根据环境的不同转换代码</li></ul><p>接下来更改 <code>webpack-config.js</code> 中的代码</p><pre><code>module.exports = { // ...... module: { rules: [ { // js 文件才使用 babel test: /\.js$/, // 使用哪个 loader use: 'babel-loader', // 不包括路径 exclude: /node_modules/, }, ], },}</code></pre><p>配置 Babel 有很多方式,这里推荐使用 .babelrc 文件管理。</p><pre><code>// ..babelrc{ "presets": ["babel-preset-env"]}</code></pre><p>现在将之前 JS 的代码改成 ES6 的写法</p><pre><code>// sum.jsexport default (a, b) => { return a + b}// index.jsimport sum from './sum'console.log(sum(1, 2))</code></pre><p>执行 <code>npm run start</code>,再观察 <code>bundle.js</code> 中的代码,可以发现代码被转换过了,并且同样可以正常 输出 3。</p><p>当然 Babel 远不止这些功能,有兴趣的可以前往官网自己探索。</p><h3 id="处理图片"><a href="#处理图片" class="headerlink" title="处理图片"></a>处理图片</h3><p>这一小节我们将使用 <code>url-loader</code> 和 <code>file-loader</code>,这两个库不仅可以处理图片,还有其他的功能,有兴趣的可以自行学习。</p><p>先安装库</p><pre><code>npm i --save-dev url-loader file-loader</code></pre><p>创建一个 <code>images</code> 文件夹,放入两张图片,并且在 <code>app</code> 文件夹下创建一个 js 文件处理图片 ,目前的文件夹结构如图</p><p><img src="-9966a1b6-ed98-4df8-9dd5-7e8bb94daf186e945ab1dc6b1881bf49fe172d4b63cf" alt=""></p><pre><code>// addImage.jslet smallImg = document.createElement('img')// 必须 require 进来smallImg.src = require('../images/small.jpeg')document.body.appendChild(smallImg)let bigImg = document.createElement('img')bigImg.src = require('../images/big.jpeg')document.body.appendChild(bigImg)</code></pre><p>接下来修改 <code>webpack.config.js</code> 代码</p><pre><code>module.exports = { // ... module: { rules: [ // ... { // 图片格式正则 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: 'url-loader', // 配置 url-loader 的可选项 options: { // 限制 图片大小 10000B,小于限制会将图片转换为 base64格式 limit: 10000, // 超出限制,创建的文件格式 // build/images/[图片名].[hash].[图片格式] name: 'images/[name].[hash].[ext]', }, }, ], }, ], },}</code></pre><p>运行 <code>npm run start</code>,打包成功如下图</p><p><img src="-3c03fac3-1985-4d14-8a7a-c02b847ef701b460ba75c92052ffd2df037b76af7ddb" alt=""></p><p>可以发现大的图片被单独提取了出来,小的图片打包进了 <code>bundle.js</code> 中。</p><p>在浏览器中打开 HTML 文件,发现小图确实显示出来了,但是却没有看到大图,打开开发者工具栏,可以发现我们大图的图片路径是有问题的,所以我们又要修改 <code>webpack.config.js</code> 代码了。</p><pre><code>module.exports = { entry: './app/index.js', // 入口文件 output: { path: path.resolve(__dirname, 'build'), // 必须使用绝对地址,输出文件夹 filename: 'bundle.js', // 打包后输出文件的文件名 publicPath: 'build/', // 知道如何寻找资源 }, // ...}</code></pre><p>最后运行下 <code>npm run start</code>,编译成功了,再次刷新下页面,可以发现这次大图被正确的显示了。下一小节我们将介绍如何处理 CSS 文件。</p><h3 id="处理-CSS-文件"><a href="#处理-CSS-文件" class="headerlink" title="处理 CSS 文件"></a>处理 CSS 文件</h3><p>添加 <code>styles</code> 文件夹,新增 <code>addImage.css</code> 文件,然后在该文件中新增代码</p><pre><code>img { border: 5px black solid;}.test { border: 5px black solid;}</code></pre><p>这一小节我们先使用 <code>css-loader</code> 和 <code>style-loader</code> 库。前者可以让 CSS 文件也支持 <code>impost</code>,并且会解析 CSS 文件,后者可以将解析出来的 CSS 通过标签的形式插入到 HTML 中,所以后面依赖前者。</p><pre><code>npm i --save-dev css-loader style-loader</code></pre><p>首先修改 <code>addImage.js</code> 文件</p><pre><code>import '../styles/addImage.css'let smallImg = document.createElement('img')smallImg.src = require('../images/small.jpeg')document.body.appendChild(smallImg)// let bigImg = document.createElement('img')// bigImg.src = require('../images/big.jpeg')// document.body.appendChild(bigImg)</code></pre><p>然后修改 <code>webpack.config.js</code> 代码</p><pre><code>module.exports = { // ... module: { rules: [ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, }, }, ], }, ], },}</code></pre><p>运行下 <code>npm run start</code>,然后刷新页面,可以发现图片被正确的加上了边框,现在我们来看一下 HTML 的文件结构</p><p><img src="-8787bb19-208c-46ac-8c66-2aa40f443936aa11101b8e22e4dd6b8c6432cfa26e03" alt=""></p><p>从上图可以看到,我们在 <code>addImage.css</code> 文件中写的代码被加入到了 <code>style</code> 标签中,并且因为我们开启了 CSS 模块化的选项,所以 <code>.test</code> 被转成了唯一的哈希值,这样就解决了 CSS 的变量名重复问题。</p><p>但是将 CSS 代码整合进 JS 文件也是有弊端的,大量的 CSS 代码会造成 JS 文件的大小变大,操作 DOM 也会造成性能上的问题,所以接下来我们将使用 <code>extract-text-webpack-plugin</code> 插件将 CSS 文件打包为一个单独文件</p><p>首先安装 <code>npm i --save-dev extract-text-webpack-plugin</code></p><p>然后修改 <code>webpack.config.js</code> 代码</p><pre><code>const ExtractTextPlugin = require("extract-text-webpack-plugin")module.exports = {// .... module: { rules: [ { test: /\.css$/, // 写法和之前基本一致 loader: ExtractTextPlugin.extract({ // 必须这样写,否则会报错 fallback: 'style-loader', use: [{ loader: 'css-loader', options: { modules: true } }] }) ] } ] }, // 插件列表 plugins: [ // 输出的文件路径 new ExtractTextPlugin("css/[name].[hash].css") ] }</code></pre><p>运行下 <code>npm run start</code>,可以发现 CSS 文件被单独打包出来了</p><p><img src="-e5bdd328-c0bc-489d-901c-5ec061fe726f343a4f4e729dc87f0ba67a652128dea3" alt=""></p><p>但是这时候刷新页面会发现图片的边框消失了,那是因为我们的 HTML 文件没有引用新的 CSS 文件,所以这里需要我们手动引入下,在下面的章节我们会通过插件的方式自动引入新的文件。</p><p>接下来,会用一个项目来继续我们的 webpack 学习,在这之前,先 clone 一下项目。该项目原地址是 <a href="https://github.com/StephenGrider/WebpackProject" target="_blank" rel="noopener">这里</a>,因为使用的 webpack 版本太低,并且依赖的库也有点问题,故我将项目拷贝了过来并修改了几个库的版本号。</p><p>请依次按照以下代码操作</p><pre><code>git clone https://github.com/KieSun/webpack-demo.gitcd webpack-demo// 切换到 0.1 标签上并创建一个新分支git checkout -b demo 0.1cd projectnpm i// 查看分支是否为 demo,没问题的话就可以进行下一步</code></pre><h2 id="如何在项目中使用-webpack"><a href="#如何在项目中使用-webpack" class="headerlink" title="如何在项目中使用 webpack"></a>如何在项目中使用 webpack</h2><p>项目中已经配置了很简单的 babel 和 webpack,直接运行 <code>npm run build</code> 即可</p><p><img src="-357436ab-9d62-49e0-a1ba-590be561484595957c4402c35a8458ed848d1d193513" alt=""></p><p>这时候你会发现这个 bundle.js 居然有这么大,这肯定是不能接受的,所以接下来章节的主要目的就是将单个文件拆分为多个文件,优化项目。</p><h3 id="分离代码"><a href="#分离代码" class="headerlink" title="分离代码"></a>分离代码</h3><p>先让我们考虑下缓存机制。对于代码中依赖的库很少会去主动升级版本,但是我们自己的代码却每时每刻都在变更,所以我们可以考虑将依赖的库和自己的代码分割开来,这样用户在下一次使用应用时就可以尽量避免重复下载没有变更的代码,那么既然要将依赖代码提取出来,我们需要变更下入口和出口的部分代码。</p><pre><code>// 这是 packet.json 中 dependencies 下的const VENOR = [ 'faker', 'lodash', 'react', 'react-dom', 'react-input-range', 'react-redux', 'redux', 'redux-form', 'redux-thunk',]module.exports = { // 之前我们都是使用了单文件入口 // entry 同时也支持多文件入口,现在我们有两个入口 // 一个是我们自己的代码,一个是依赖库的代码 entry: { // bundle 和 vendor 都是自己随便取名的,会映射到 [name] 中 bundle: './src/index.js', vendor: VENOR, }, output: { path: path.join(__dirname, 'dist'), filename: '[name].js', }, // ...}</code></pre><p>现在我们 build 一下,看看是否有惊喜出现</p><p><img src="-346cfe1f-5088-4864-a4d4-2768df954807370471eb63feeaa72e86415e396141e3" alt=""></p><p><img src="-39becdb0-4205-4be0-9468-29741ef0dcc048be1794942ddaf2f030bbb3a09de61a" alt=""></p><p>真的有惊喜。。为什么 bundle 文件大小压根没变。这是因为 bundle 中也引入了依赖库的代码,刚才的步骤并没有抽取 bundle 中引入的代码,接下来让我们学习如何将共同的代码抽取出来。</p><h3 id="抽取共同代码"><a href="#抽取共同代码" class="headerlink" title="抽取共同代码"></a>抽取共同代码</h3><p>在这小节我们使用 webpack 自带的插件 <code>CommonsChunkPlugin</code>。</p><pre><code>module.exports = { //... output: { path: path.join(__dirname, 'dist'), // 既然我们希望缓存生效,就应该每次在更改代码以后修改文件名 // [chunkhash]会自动根据文件是否更改而更换哈希 filename: '[name].[chunkhash].js', }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ // vendor 的意义和之前相同 // manifest文件是将每次打包都会更改的东西单独提取出来,保证没有更改的代码无需重新打包,这样可以加快打包速度 names: ['vendor', 'manifest'], // 配合 manifest 文件使用 minChunks: Infinity, }), ],}</code></pre><p>当我们重新 build 以后,会发现 bundle 文件很明显的减小了体积</p><p><img src="-8aaf7522-6187-4e16-a119-f183a87b595d0a0617d1f53173638cf9da06769bea27" alt=""></p><p>但是我们使用哈希来保证缓存的同时会发现每次 build 都会生成不一样的文件,这时候我们引入另一个插件来帮助我们删除不需要的文件。</p><pre><code>npm install --save-dev clean-webpack-plugin</code></pre><p>然后修改配置文件</p><pre><code>module.exports = { //... plugins: [ // 只删除 dist 文件夹下的 bundle 和 manifest 文件 new CleanWebpackPlugin(['dist/bundle.*.js', 'dist/manifest.*.js'], { // 打印 log verbose: true, // 删除文件 dry: false, }), ],}</code></pre><p>然后 build 的时候会发现以上文件被删除了。</p><p>因为我们现在将文件已经打包成三个 JS 了,以后也许会更多,每次新增 JS 文件我们都需要手动在 HTML 中新增标签,现在我们可以通过一个插件来自动完成这个功能。</p><pre><code>npm install html-webpack-plugin --save-dev</code></pre><p>然后修改配置文件</p><pre><code>module.exports = { //... plugins: [ // 我们这里将之前的 HTML 文件当做模板 // 注意在之前 HTML 文件中请务必删除之前引入的 JS 文件 new HtmlWebpackPlugin({ template: 'index.html', }), ],}</code></pre><p>执行 build 操作会发现同时生成了 HTML 文件,并且已经自动引入了 JS 文件</p><p><img src="-9a48247b-c009-4a7c-a3d3-246e2c818427f8a5991239c5aa45f845d1d9d4afe05d" alt=""></p><h3 id="按需加载代码"><a href="#按需加载代码" class="headerlink" title="按需加载代码"></a>按需加载代码</h3><p>在这一小节我们将学习如何按需加载代码,在这之前的 vendor 入口我发现忘记加入 router 这个库了,大家可以加入这个库并且重新 build 下,会发现 bundle 只有不到 300KB 了。</p><p>现在我们的 bundle 文件包含了我们全部的自己代码。但是当用户访问我们的首页时,其实我们根本无需让用户加载除了首页以外的代码,这个优化我们可以通过路由的异步加载来完成。</p><p>现在修改 <code>src/router.js</code></p><pre><code>// 注意在最新版的 V4路由版本中,更改了按需加载的方式,如果安装了 V4版,可以自行前往官网学习import React from 'react'import { Router, Route, IndexRoute, hashHistory } from 'react-router'import Home from './components/Home'import ArtistMain from './components/artists/ArtistMain'const rootRoute = { component: Home, path: '/', indexRoute: { component: ArtistMain }, childRoutes: [ { path: 'artists/new', getComponent(location, cb) { System.import('./components/artists/ArtistCreate').then(module => cb(null, module.default) ) }, }, { path: 'artists/:id/edit', getComponent(location, cb) { System.import('./components/artists/ArtistEdit').then(module => cb(null, module.default) ) }, }, { path: 'artists/:id', getComponent(location, cb) { System.import('./components/artists/ArtistDetail').then(module => cb(null, module.default) ) }, }, ],}const Routes = () => { return <Router history={hashHistory} routes={rootRoute} />}export default Routes</code></pre><p>然后执行 build 命令,可以发现我们的 bundle 文件又瘦身了,并且新增了几个文件</p><p><img src="-e0271ed9-5ff5-4cc3-bc42-13f4af521c7c8e48f667bb4313db100105b7dc34cdb2" alt=""></p><p>将 HTML 文件在浏览器中打开,当点击路由跳转时,可以在开发者工具中的 Network 一栏中看到加载了一个 JS 文件。</p><p>首页</p><p><img src="-66762fc8-74a1-40e5-b213-54aa2696a088a5a9c677fc770d8a99bbed9e79fdd730" alt=""></p><p>点击右上角 Random Artist 以后</p><p><img src="-48d331f9-db45-4f31-a86f-dd10001b755f93e7c9d86eeb7076b6f5e7434b0012e9" alt=""></p><h3 id="自动刷新"><a href="#自动刷新" class="headerlink" title="自动刷新"></a>自动刷新</h3><p>每次更新代码都需要执行依次 build,并且还要等上一会很麻烦,这一小节介绍如何使用自动刷新的功能。</p><p>首先安装插件</p><pre><code>npm i --save-dev webpack-dev-server</code></pre><p>然后修改 packet.json 文件</p><pre><code>"scripts": { "build": "webpack", "dev": "webpack-dev-server --open" },</code></pre><p>现在直接执行 <code>npm run dev</code> 可以发现浏览器自动打开了一个空的页面,并且在命令行中也多了新的输出</p><p><img src="-4af5c77f-730f-4200-977a-6e9bab54b4b843f5b70bd82152ce21379120dfab8d71" alt=""></p><p>等待编译完成以后,修改 JS 或者 CSS 文件,可以发现 webpack 自动帮我们完成了编译,并且只更新了需要更新的代码</p><p><img src="-7e486a43-aa30-4610-a6d3-246e45cd5cc17a5769363d0782abc59902d370c52472" alt=""></p><p>但是每次重新刷新页面对于 debug 来说很不友好,这时候就需要用到模块热替换了。但是因为项目中使用了 React,并且 Vue 或者其他框架都有自己的一套 hot-loader,所以这里就略过了,有兴趣的可以自己学习下。</p><h3 id="生成生产环境代码"><a href="#生成生产环境代码" class="headerlink" title="生成生产环境代码"></a>生成生产环境代码</h3><p>现在我们可以将之前所学和一些新加的插件整合在一起,build 生产环境代码。</p><pre><code>npm i --save-dev url-loader optimize-css-assets-webpack-plugin file-loader extract-text-webpack-plugin</code></pre><p>修改 webpack 配置</p><pre><code>var webpack = require('webpack')var path = require('path')var HtmlWebpackPlugin = require('html-webpack-plugin')var CleanWebpackPlugin = require('clean-webpack-plugin')var ExtractTextPlugin = require('extract-text-webpack-plugin')var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')const VENOR = [ 'faker', 'lodash', 'react', 'react-dom', 'react-input-range', 'react-redux', 'redux', 'redux-form', 'redux-thunk', 'react-router',]module.exports = { entry: { bundle: './src/index.js', vendor: VENOR, }, // 如果想修改 webpack-dev-server 配置,在这个对象里面修改 devServer: { port: 8081, }, output: { path: path.join(__dirname, 'dist'), filename: '[name].[chunkhash].js', }, module: { rules: [ { test: /\.js$/, use: 'babel-loader', }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: 'url-loader', options: { limit: 10000, name: 'images/[name].[hash:7].[ext]', }, }, ], }, { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ { // 这边其实还可以使用 postcss 先处理下 CSS 代码 loader: 'css-loader', }, ], }), }, ], }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'manifest'], minChunks: Infinity, }), new CleanWebpackPlugin(['dist/*.js'], { verbose: true, dry: false, }), new HtmlWebpackPlugin({ template: 'index.html', }), // 生成全局变量 new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('process.env.NODE_ENV'), }), // 分离 CSS 代码 new ExtractTextPlugin('css/[name].[contenthash].css'), // 压缩提取出的 CSS,并解决ExtractTextPlugin分离出的 JS 重复问题 new OptimizeCSSPlugin({ cssProcessorOptions: { safe: true, }, }), // 压缩 JS 代码 new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, }, }), ],}</code></pre><p>修改 packet.json 文件</p><pre><code>"scripts": { "build": "NODE_ENV=production webpack -p", "dev": "webpack-dev-server --open" }</code></pre><p>执行 <code>npm run build</code></p><p><img src="-ed5569b4-1311-43ee-b87b-426ac8422b98ff8acf374946ee6db118117f22ec48f5" alt=""></p><p>可以看到我们在经历了这么多步以后,将 bundle 缩小到了只有 27.1KB,像 vendor 这种常用的库我们一般可以使用 CDN 的方式外链进来。</p><h2 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h2><p>webpack 配置上有些实用的小点在上文没有提到,统一在这里提一下。</p><pre><code>module.exports = { resolve: { // 文件扩展名,写明以后就不需要每个文件写后缀 extensions: ['.js', '.css', '.json'], // 路径别名,比如这里可以使用 css 指向 static/css 路径 alias: { '@': resolve('src'), css: resolve('static/css'), }, }, // 生成 source-map,用于打断点,这里有好几个选项 devtool: '#cheap-module-eval-source-map',}</code></pre><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>如果你是跟着本文一个个步骤敲下来的,那么大部分的 webpack 配置你应该都是可以看懂了,并且自己应该也知道如何去配置。谢谢大家看到这里,<a href="https://github.com/KieSun/webpack-demo" target="_blank" rel="noopener">这是本项目对应的仓库</a>,每个小节基本都对应了一次 commit。</p><p>文章较长,有错误也难免,如果你发现了任何问题或者我有任何表述的不明白的地方,都可以留言给我。</p><p><img src="-36add5b0-d75b-4e8c-ba9b-69b005e0a76a1611c102b6ef7869" alt=""></p>]]></content>
<summary type="html">
<blockquote>
<p>该文使用的 Webpack 版本为 3.6.0,本文分两部分。第一步是简单的使用 webpack,第二部分通过一个真实项目来配置 webpack,没有使用任何的 CLI,都是一步步配置直到完成生产代码的打包。这是本项目对应的仓库,每个小节基本都对应
</summary>
<category term="前端" scheme="https://blog.yanng.io/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>深入理解 ES6</title>
<link href="https://blog.yanng.io/2018/12/12/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20ES6/"/>
<id>https://blog.yanng.io/2018/12/12/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20ES6/</id>
<published>2018-12-12T14:43:57.000Z</published>
<updated>2019-02-27T15:34:35.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>本文篇幅较长,有兴趣的可以先收藏再看。本文将重要的 ES6 特性介绍了一遍,并且详细解释了一些重难点。</p></blockquote><h2 id="let-amp-amp-const"><a href="#let-amp-amp-const" class="headerlink" title="let && const"></a>let && const</h2><p><code>let</code> 与 <code>var</code> 的声明用法相同,但是多了一个临时死区(Temporal Distonrtion Zone)的概念。</p><pre><code>console.log(a) // -> undefinedvar a = 1console.log(b) // -> Uncaught ReferenceError: b is not definedlet b = 1</code></pre><p>可以发现在声明前使用 <code>let</code> 声明的变量会导致报错,这解决了 JS 很多奇怪的问题。并且使用 <code>let</code> 会生成一个块级作用域,作用域外不能访问该变量。</p><pre><code>{ let a = 1 var b = 1}console.log(b) // -> 1console.log(a) // -> Uncaught ReferenceError: b is not defined</code></pre><p>在 JS 中,声明变量都会提升,不论用什么关键字声明。当使用 <code>let</code> 时变量也会被提升至块级作用域的顶部,但是只提升声明,不提升初始化。并且会产生临时死区,该区域会存放变量,直到执行过声明语句后,方可使用该变量。</p><p>在循环中 <code>let</code> 会与前面有些不同,每次迭代都会产生一个新的变量,并用之前的值初始化,如何理解这句话呢,请看以下代码。</p><pre><code>for(let i = 0; i < 10; i++) { console.log(i) // -> 输入 0 - 9}// 上面的循环代码可以这样看{ // 形成块级作用域 let i = 0 { let ii = i console.log(ii) } i++ { let ii = i console.log(ii) } i++ { let ii = i console.log(ii) } ...}</code></pre><p><code>const</code> 与 <code>let</code> 基本类似,只是用 <code>const</code> 声明必须赋值,并且不得修改绑定,什么意思呢,请看代码。</p><pre><code>const a = 1a = 2 // -> Uncaught TypeError: Assignment to constant variable// butconst b = { a: 1 }b.a = 2 // 起效</code></pre><p>当然了,有办法让这个不能改变</p><pre><code>const b = Object.freeze({ a: 1 })b.a = 2 // 没有报错,但是 b.a 没有被改变</code></pre><p>但是 <code>Object.freeze</code> 只能在这里有效,对于数组这些可以看看这个<a href="https://github.com/sebmarkbage/ecmascript-immutable-data-structures" target="_blank" rel="noopener">提案</a>。</p><blockquote><p>这两个新的声明方式在全局作用域下不会自动加上 window</p></blockquote><h2 id="字符串相关"><a href="#字符串相关" class="headerlink" title="字符串相关"></a>字符串相关</h2><h3 id="部分新增的字符串函数"><a href="#部分新增的字符串函数" class="headerlink" title="部分新增的字符串函数"></a>部分新增的字符串函数</h3><pre><code>let string = 'startend'string.includes('a') // -> true 是否包含string.endsWith('end') // -> true 是否由 end 结尾string.startsWith('start') // -> true 是否由 start 开头</code></pre><h3 id="模板字面量"><a href="#模板字面量" class="headerlink" title="模板字面量"></a>模板字面量</h3><p>很棒的新功能,解决了之前很多麻烦的写法。</p><pre><code>// 语法就是 `` 代替之前的引号,在 `` 中使用引号不需要转义let s = `it's string`</code></pre><p>多行字符串</p><pre><code>// 这样在语法中就可以换行了let s = `start \end`// 注意在模板字面量中的任何空白符都是起效的let s = `start \ end` // -> start end</code></pre><p>占位符和标签模板</p><pre><code>let s = 'string'let message = `start${s}` // -> startstring// ${} 就是占位符语法,可以更简便的实现字符串插入// 定义一个 tag 函数,然后直接在 `` 前使用就可以let m = tag`s${s}e${message}`// strings 是一个数组,value 是模板字面量中所有的占位符的值function tag(strings, ...value) { // -> ['s', 'e', ''] console.log(strings) // -> ['string', 'startstring'] console.log(value)}// 上面的 ...value 也是 ES6新出的扩展语句,在这里代表不定参数的写法,用于替换 arguments// 不定参数使用上也是有限制的,必须放在所有参数的末尾,并且在每个函数中只能声明一次// 扩展语句和 arguments 区别就是代表了 strings 参数后面的所有参数// 除了上面的写法,还可以用于展开可以迭代(有Symbol.iterator属性)的对象let array = [1, 2, 3]console.log(...array)// 该语法可以解决之前很多地方只能传入单个参数,只能使用 apply 解决的问题Array.prototype.unshift .apply([4, 5], array) // -> [1, 2, 3, 4, 5] [ // 现在可以直接这样写 (4, 5) ].unshift(...array)// 展开运算不受不定参数的条件限制,可以一起用</code></pre><h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><h3 id="默认参数"><a href="#默认参数" class="headerlink" title="默认参数"></a>默认参数</h3><p>ES6 允许给函数增加默认参数</p><pre><code>function fn(a = 1, b = 2) {}// 默认值也可以通过调用函数获得,注意必须调用函数function fn1(a = 1, b = fn()) {}</code></pre><h3 id="新增函数内部方法"><a href="#新增函数内部方法" class="headerlink" title="新增函数内部方法"></a>新增函数内部方法</h3><p>在 JS 中,函数有多种用法,可以直接调用,也可以通过 <code>new</code> 构造函数。</p><p>在 ES6 中,函数内部新增了 [[Call]] 和 [[Construct]] 两个方法。后者会在使用 <code>new</code> 构造函数时执行,其他情况会执行前者方法。</p><p>当一个函数必须使用 <code>new</code> 构造时,你可以使用这个新属性 <code>new.target</code> 判断</p><pre><code>// new.target 只能在函数中使用function Fn() { if (typeof new.target === 'underfined') { throw ....... }}</code></pre><h3 id="箭头函数"><a href="#箭头函数" class="headerlink" title="箭头函数"></a>箭头函数</h3><p>这个特性真的很棒,先介绍下他的几种语法</p><pre><code>// 最简单的写法,只有一个参数,单行表达式value => value// 多个参数需要使用小括号包裹(v1, v2) => v2 + v1// 没有参数需要使用小括号包裹() => "balabala"// 多行表达式需要大括号包裹(v1, v2) => { return v1 + v2}// 返回一个对象,需要用小括号包裹() => ({a: 1})// 立即执行函数,注意普通的立即执行函数的小括号包裹在最外面,箭头函数不需要((value) => value)("balabala")</code></pre><p>箭头函数和普通函数区别还是蛮大的,说几个常用的</p><ul><li>没有 <code>this</code>,不能改变 <code>this</code> 绑定</li><li>不能通过 <code>new</code> 调用,当然也没有原型</li><li>没有 <code>arguments</code> 对象,不能有相同命名参数</li></ul><p>箭头函数虽然没有 <code>this</code> ,但是还是可以在内部使用 <code>this</code> 的</p><ul><li><p><code>this</code> 的绑定取决于定义函数时的上下文环境</p></li><li><p>一旦函数调用,任何改变 <code>this</code> 的方法都无效</p><p> // let 有个细节<br> let x = 11111<br> let a = {</p><pre><code>x: 1,init() { // 箭头函数的 this 取决于 init,所以可以打印出 1 document.addEventListener('click', () => console.log(this.x))},allowInit: () => { // allowInit 直接是个箭头函数,所以这时的 this 变成了 window // 但是并不会打印出 11111,忘了 let 的一个细节的可以回到上面看看 console.log(this.x))}otherInit() { // 普通函数的 this 取决于调用函数的位置,this 指向 document // 如果想打印出 x,可以使用 bind document.addEventListener('click', function() { console.log(this.x) })}</code></pre><p> }<br> a.init() // -> 1<br> a.allowInit() // -> undefined<br> a.otherInit() // -> undefined</p></li></ul><h2 id="对象相关"><a href="#对象相关" class="headerlink" title="对象相关"></a>对象相关</h2><pre><code>let a = 1// 当 key 和 value 名字相同时可以简写let b = { a }// 对象中的方法也可以简写let a = { init() {},}// 对象属性名也可以计算let name = 'name'b[name + '1'] = 2 // === b['name1'] = 2</code></pre><p>ES6 也新增了几个对象方法</p><pre><code>Object.is(NaN, NaN) // ->true// 结果基本于 === 相似,除了 NaN 和 +0 -0Object.is(+0, -0) // -> falselet o = { a: 1 }let a = Object.assign({}, o) // -> {a: 1}// 第一个参数为目标参数,后面的参数是不定的,参数属性名如果有重复,后面的会覆盖之前的</code></pre><p>原型相关</p><p>ES6 之前改变对象原型很麻烦</p><pre><code>let obj = { a: 1 }let obj1 = { a: 2 }// 已 obj 为原型let a = Object.create(obj)// 改变 a 的原型为 obj1Object.setPrototypeOf(a, obj1) // a.a === 2</code></pre><p>访问原型</p><pre><code>Object.getPrototypeOf(a) // 访问原型// ES6 中可以直接通过 super 代表原型let a = { init() { return 'Hello' },}let b = { init() { // 不能在 super 之前访问 this return super.init() + 'World' },}Object.setPrototypeOf(b, a)b.init() // -> 'HelloWorld'</code></pre><p>但是 super 不是每个函数都可以使用的,只有在函数的简写语法中方可使用。因为在 ES6 中新增了一个函数内部属性 [[HomeObject]],这个属性决定了是否可以访问到 <code>super</code>。首先在该属性上调用 <code>Object.getPrototypeOf(绑定的对象)</code>,然后找到原型中的同名函数,在设置 <code>this</code> 绑定并且调用函数,其实就是一个新增的语法糖。</p><h2 id="解构赋值"><a href="#解构赋值" class="headerlink" title="解构赋值"></a>解构赋值</h2><p>该特性可以用于对象,数组和传参。</p><pre><code>let obj = { a: 1, b: 2 }// 对象解构使用 {},数组解构使用 [],因为这里是对象解构,c 不是 obj 的属性,所以 underfined// 数组解构中,如果需要解构的变量大于数组索引,多出来的变量也是 undefined// 解构必须赋值,否则报错。不能 let {a, b, c};// 赋值不能为 null 或者 undefined,会报错let { a, b, c } = obj// 等于 let a = obj.a,可以看做之前介绍的对象属性简写console.log(a, b, c)( // -> 1, 2, underfined // 如果已经声明了变量并且想使用解构,必须最外面是小括号 ({ a, b } = obj))// 如果不想使用 obj 中的对象名,又想使用解构赋值let { x: a } = obj// 如果想使用默认值let { a = 2, c = 3 } = obj // -> 1, 3// 因为 a 是 obj 中的对象,所以默认值被覆盖// 解构也可以嵌套let obj = { data: { code: 1 }, message: [1, 2] }// 这个写法在 json 中很好用// 注意在这个写法中,data 和 message 都是指代了 obj 的属性,并没有被声明变量let { data: { code }, message: [a],} = objconsole.log(code, a)// 数组解构和对象解构基本相似,并且简单多了let message = [1, 2, 3, 4]// 因为数组取值只能索引取,所以想跳过某几个索引,就用逗号代替// 同样,数组解构也可以使用默认值和嵌套解构,和对象解构一模一样就不赘述了let [a, , b] = message // -> 1, 3// 在上面章节介绍了扩展语法,同样也可以使用在数组解构中// 可以看到 b 变成了一个数组let [a, ...b] = message // -> 1, [2, 3, 4]// 传参使用解构可以让要传的参数更加清晰function fn(name, { key, value }) { console.log(name, key, value)}// 使用,注意:传参解构必须起码传入一个值,否则报错fn(1, { key: 2, value: 3 })// 因为传参解构类似以下写法function fn(name, { key, value }) { let { key, value } = null // 这个上面讲过不能这样写}</code></pre><h2 id="Symbol"><a href="#Symbol" class="headerlink" title="Symbol"></a>Symbol</h2><p>ES6 新出的第六个原始类型。多用于避免代码冲突,作为一个私有属性使用,不会被属性遍历出来。可以使用 <code>Object.getOwnPropertySymbols()</code> 检索 Symbol 属性。</p><h3 id="创建和使用"><a href="#创建和使用" class="headerlink" title="创建和使用"></a>创建和使用</h3><pre><code>// 创建let a = Symbol()// 更推荐这种写法,可以更加明确这个Symbol的用途// 并且有函数可以通过这个字符串取到相应的Symbollet b = Symbol('is b')// 使用,一般作为可计算属性使用let a = {}let b = Symbol('is b')a[b] = 1// 可以在全局注册表中共享同一个 Symbol,但不推荐使用// 不存在 is a 会自动创建let a = Symbol.for('is a')</code></pre><h3 id="暴露内部操作"><a href="#暴露内部操作" class="headerlink" title="暴露内部操作"></a>暴露内部操作</h3><p>Symbol 中预定义了一些 well-know Symbol,这些 Symbol 定义了一些语言的内部实现</p><ul><li>Symbol.hasinstance,用于执行 <code>instanceof</code> 时检测对象的继承信息</li><li>Symbol.isConcatSpreadable,布尔值,用于判断当使用 <code>concat</code> 函数时是否将数组展开</li><li>Symbol.iterator,迭代器,后面会讲到</li><li>Symbol.match,Symbol.replace,Symbol.search,Symbol.split,字符串相关方法的对应内部实现</li><li>Symbol.toPrimitive,返回对象原始值</li><li>Symbol.toStringTag,调用 <code>toString</code></li></ul><h2 id="Set-和-Map"><a href="#Set-和-Map" class="headerlink" title="Set 和 Map"></a>Set 和 Map</h2><h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p>Set 是新增的无重复的有序集合,多用于集合去重或者判断集合中是否含有某个元素。</p><pre><code>// 创建let set = new Set()// 添加元素set.add(1)set.add('1')// 重复的元素不会被添加set.add(1)// 判断是否包含元素set.has(1) // -> true// 判断长度set.size() // -> 2// 删除某个元素set.delete()// 移除所有元素set.clear()</code></pre><h3 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h3><p>Map 是新增的有序键值对列表,键值可以是任何类型。</p><pre><code>// 创建let map = new Map()// 设置键值对map.set('year', '2017')map.set({}, 'obj')// 取值map.get('year') // -> '2017'// 判断是否有该键值map.has('year') // -> true// 获得长度map.size() // -> 2// 删除某个键值map.delete('year')// 移除所有键值map.clear()</code></pre><h2 id="迭代器和-Generator-函数"><a href="#迭代器和-Generator-函数" class="headerlink" title="迭代器和 Generator 函数"></a>迭代器和 Generator 函数</h2><h3 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h3><p>顾名思义,用来迭代的。之前介绍过 <code>Symbol.iterator</code>,可以迭代的对象都有这个属性,包括数组,Set,Map,字符串和 NodeList。ES6 新增的 <code>for-of</code> 就用到了迭代器的功能,但是默认只有上面这些对象能使用。</p><pre><code>let a = [1, 2]for (let value of a) { console.log(value) // -> 1, 2}// 上面的代码其实就是调用了数组的默认迭代器let iterator = a[Symbol.iterator]()// 当调用 next 时会输出这次迭代的 value 和是否迭代完成console.log(iterator.next()) // {value: 1, done: false}console.log(iterator.next()) // {value: 2, done: false}// 已经没元素可以迭代了console.log(iterator.next()) // {value: undefined, done: true}// 数组的默认迭代器只会输出 value,如果想同时输出索引的话// 这里可以使用新特性数组解构 let [index, value]for (let value of a.entries()) { console.log(value) // -> [0, 1] [1, 2]}</code></pre><p>对于自己创建的对象都是不可迭代的,当然我们也可以让他变成迭代的</p><pre><code>let a = { array: [], // 这是一个 Generator 函数,马上就会讲到 *[Symbol.iterator]() { for (let item in this.array) { yield item } },}a.array.push(...[1, 2, 3])for (let item of a) { console.log(item)}</code></pre><h3 id="Generator-函数"><a href="#Generator-函数" class="headerlink" title="Generator 函数"></a>Generator 函数</h3><p>用于异步编程。该函数可以暂停和恢复执行,和同步写法很像。</p><pre><code>// 星号表示这是一个 Generator 函数function* gen() { // 第一次 next 只执行到等号右边 let first = yield 1 // 第二次 next 执行 let first = 和 yield 2 let second = yield 2 // 不执行接下来的 next 就卡在上一步了 let thrid = yield 3}let g = gen()g.next() // -> {value: 1, done: false}g.next() // -> {value: 2, done: false</code></pre><p>接下来看下 Generator 函数如何用于异步</p><pre><code>function getFirstName() { setTimeout(function() { gen.next('alex') }, 1000)}function getSecondName() { setTimeout(function() { gen.next('perry') }, 2000)}function* sayHello() { var a = yield getFirstName() var b = yield getSecondName() // settimeout 本来是异步的,通过 Generator 函数写成了同步写法 console.log(a, b) // ->alex perry}var gen = sayHello()gen.next()</code></pre><h2 id="类"><a href="#类" class="headerlink" title="类"></a>类</h2><p>JS 中的类不是其他语言中的类,只是个语法糖,写法如下。</p><pre><code>class Person { // 构造函数 constructor() { this.name = name } sayName() { console.log(this.name) }}let p = new Person('name')p.sayName() // -> 'name'// class 就是以下代码的语法糖// 对应 constructorfunction Person(name) { this.name = name}// 对应 sayNamePerson.prototype.sayName = function() { console.log(this.name)}</code></pre><p>类声明相比之前的写法有以下几点优点</p><ul><li>类声明和 let 声明一样,有临时死区</li><li>类声明中的代码全部运行在严格模式下</li><li>必须使用 new 调用</li></ul><h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3><p>在 ES6 之前写继承很麻烦,既然有个类,那么必然也可以继承类了</p><pre><code>class Person { // 构造函数 constructor() { this.name = name } sayName() { console.log(this.name) }}// extends 代表继承自Personclass Student extends Person { constructor(name, age) { // super 的注意事项之前有说过 super(name) // 必须在 super 之后调用 this this.age = age } sayName() { // 如果像使用父类的方法就使用这个方法使用 // 不像使用的话就不写 super,会覆盖掉父类的方法 super.sayName(this.name) console.log(this.age) }}</code></pre><h2 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>用于异步编程。</p><pre><code>// 你可以使用 new 创建一个 Promise 对象let promise = new Promise(function(resolve, reject)) {}resole() // 代表成功reject() // 代表失败promise.then(onFulfilled, onRejected) // 当调用 resole 或者 reject ,then 可以监听到promise.catch() // reject 或者 throw时可以监听到</code></pre><p>Promise 有三个状态</p><ul><li>pending,等待状态,也就是既不是 resolve 也不是 reject 状态</li><li>fulfilled,resolve 以后进入这个状态</li><li>reject,reject 以后进入这个状态</li></ul><h3 id="一般使用情况"><a href="#一般使用情况" class="headerlink" title="一般使用情况"></a>一般使用情况</h3><pre><code>function delay() { // 创建一个 promise return new Promise((resolve, reject) => { // 当调用 promise 时,里面的内容会立即执行 console.log('in delay') setTimeout(() => { resolve(1) }, 1000) })}function otherDelay() { return new Promise((resolve, reject) => { setTimeout(() => { reject(1) }, 1000) })}// 这里会先输出 delay 函数中的 log,然后再输出 outer,接下来1秒以后输出3个1delay() // then 可以捕获 resolve 和 reject .then(value => { console.log(value) })console.log('outer')otherDelay() // 捕获 reject时,如果不需要捕获 resolve 时可以这样写 .then(null, value => { console.log(value) })// 捕获 reject 或者 throw 时推荐使用这个写法,原因后面会说otherDelay().catch(value => { console.log(value)})</code></pre><p>以上是最常用的 Promise 写法,现在介绍 Promise 链</p><pre><code>delay() // then 会返回一个新的 promise 对象 .then(value => { // 这样就可以传参了 return value + 1 }) .then(value => { console.log(value) // -> 2 // then 里面可以也可以传入一个函数名,会自动调用 // 如果传入的函数有参数会自动传入 }) .then(delay) .then(value => { console.log(value) // -> 1 // 如果在then 中抛出错误,只有 catch 才能监听到,所以推荐使用 catch 监听错误 throw new Error('error') }) .then(value => { console.log(value) // 这个then 不会执行 }) .catch(error => { console.log('catch' + error) // -> catch Error })</code></pre><h3 id="Promise-高级用法"><a href="#Promise-高级用法" class="headerlink" title="Promise 高级用法"></a>Promise 高级用法</h3><p>开发中可能会有需求,需要一次上传几张图片,全部上传成功以后有个提示,这时候就可以用到 <code>Promise.all()</code></p><pre><code>function updateOne() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('one') }, 1000) })}function updateTwo() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('two') }, 2000) })}// all 函数接收一个可迭代对象,注意这里传入函数必须调用let promise = Promise.all([updateOne(), updateTwo()])// 只有当 all 中的异步全部完成了才会调用 thenpromise.then(value => { // value 是个函数,顺序按照 all 里的迭代对象的顺序 console.log(value) // -> ["one", "two"]})</code></pre><p>如果一个异步任务超时了,你想直接取消,可以通过 <code>Promise.race()</code></p><pre><code>// 假设该任务执行时间超过1秒就算超时,应该 cancelfunction delay() { return new Promise((resolve, reject) => { setTimeout(function() { resolve('finish') }, 1500) })}function cancel() { return new Promise((resolve, reject) => { setTimeout(function() { resolve('cancel') }, 1000) })}// 接收的参数和 all 相同let promise = Promise.race([delay(), cancel()])// race 中只要有一个任务完成,then 就会被调用,这样就可以 cancel 掉所有超时任务promise.then(value => { console.log(value) // -> cancel})</code></pre><h2 id="Proxy"><a href="#Proxy" class="headerlink" title="Proxy"></a>Proxy</h2><p>Proxy 可以创建一个代替目标对象的代理,拦截语言内部的操作。</p><pre><code>let handle = {}let target = {}// 这样就创建了target 对象的代理,但是这个代理其实没有任何用处let p = new Proxy(target, handle)</code></pre><p>上面的代码中可以看到传入了一个 <code>handle</code> 的对象,只有当这个对象中包含一些代理行为的函数时,这个代理才有用。具有的代理行为函数可以去 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy" target="_blank" rel="noopener">MDN</a>查看,这里举例几个用法。</p><pre><code>let handle = { // 改变 set 的内部操作 set(target, key, value) { // 当给 age 属性赋值小于19时报错 console.log(value) if (key === 'age') { if (value < 19) { throw new Error('未成年') } } },}let target = {}let p = new Proxy(target, handle)p.age = 1 // -> 报错p.age = 19 // -> 没问题</code></pre><h2 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h2><p>ES6 引入了原生的模块化,这样就可以抛弃之前的 AMD 或者 CMD 规范了,如果对模块化还没什么了解,可以看下我之前的文章 <a href="https://juejin.im/post/59a575b06fb9a0247c6eee02" target="_blank" rel="noopener">明白 JS 模块化</a>。</p><pre><code>// example.js 文件下// export 可以导出任何变量,函数或者类export var age = 14export function sum(n1, n2) { return n1 + n2}export class Person { constructor(age) { this.age = age }}// 别的 JS 文件中导入// 如果想导入整个模块并且自己命名,就可以这样使用// import 后面代表模块名,from 后面代表要导入的文件地址import * as Example from './example'console.log(Example.age) // -> 14// 当然你也可以只使用模块中的一个功能// 这里使用了对象解构的方法拿到需要的功能,注意这里名字必须相同,否则使用会报错import { age, sum } from './example'console.log(age) // -> 14console.log(sum(1, 2)) // -> 3// 现在我只想导出一个功能,并且外部可以随便命名该如何做呢?// default 一个文件中只能使用一次export default var age = 14// MyAge 可以随便自己喜欢命名import MyAge from './example'console.log(MyAge) // -> 14</code></pre>]]></content>
<summary type="html">
<blockquote>
<p>本文篇幅较长,有兴趣的可以先收藏再看。本文将重要的 ES6 特性介绍了一遍,并且详细解释了一些重难点。</p>
</blockquote>
<h2 id="let-amp-amp-const"><a href="#let-amp-amp-const
</summary>
<category term="前端" scheme="https://blog.yanng.io/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>深度解析原型中的各个难点</title>
<link href="https://blog.yanng.io/2018/11/02/%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90%E5%8E%9F%E5%9E%8B%E4%B8%AD%E7%9A%84%E5%90%84%E4%B8%AA%E9%9A%BE%E7%82%B9/"/>
<id>https://blog.yanng.io/2018/11/02/%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90%E5%8E%9F%E5%9E%8B%E4%B8%AD%E7%9A%84%E5%90%84%E4%B8%AA%E9%9A%BE%E7%82%B9/</id>
<published>2018-11-02T14:43:57.000Z</published>
<updated>2019-02-27T15:33:30.000Z</updated>
<content type="html"><![CDATA[<p>本文不会过多介绍基础知识,而是把重点放在原型的各个难点上。</p><p><img src="-a7f68c7b-187a-4c44-9718-18fa861b841f1621e8a9bcb0872d" alt=""></p><p>大家可以先仔细分析下该图,然后让我们进入主题</p><h2 id="prototype"><a href="#prototype" class="headerlink" title="prototype"></a><code>prototype</code></h2><p>首先来介绍下 <code>prototype</code> 属性。这是一个显式原型属性,只有函数才拥有该属性。基本上所有函数都有这个属性,但是也有一个例外</p><pre><code>let fun = Function.prototype.bind()</code></pre><p>如果你以上述方法创建一个函数,那么可以发现这个函数是不具有 <code>prototype</code> 属性的。</p><h3 id="prototype-如何产生的"><a href="#prototype-如何产生的" class="headerlink" title="prototype 如何产生的"></a>prototype 如何产生的</h3><p>当我们声明一个函数时,这个属性就被自动创建了。</p><pre><code>function Foo() {}</code></pre><p>并且这个属性的值是一个对象(也就是原型),只有一个属性 <code>constructor</code></p><p><code>constructor</code> 对应着构造函数,也就是 <code>Foo</code>。</p><h3 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h3><p><code>constructor</code> 是一个公有且不可枚举的属性。一旦我们改变了函数的 <code>prototype</code> ,那么新对象就没有这个属性了(当然可以通过原型链取到 <code>constructor</code>)。</p><p><img src="-a55849d0-d1ee-4661-b9be-61b08c76524e1621eaa750c877ae" alt=""></p><p>那么你肯定也有一个疑问,这个属性到底有什么用呢?其实这个属性可以说是一个历史遗留问题,在大部分情况下是没用的,在我的理解里,我认为他有两个作用:</p><ul><li>让实例对象知道是什么函数构造了它</li><li>如果想给某些类库中的构造函数增加一些自定义的方法,就可以通过 <code>xx.constructor.method</code> 来扩展</li></ul><h2 id="proto"><a href="#proto" class="headerlink" title="_proto_"></a><code>_proto_</code></h2><p>这是每个对象都有的隐式原型属性,指向了创建该对象的构造函数的原型。其实这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,我们并不能访问到,所以使用 <code>_proto_</code> 来访问。</p><p>因为在 JS 中是没有类的概念的,为了实现类似继承的方式,通过 <code>_proto_</code> 将对象和原型联系起来组成原型链,得以让对象可以访问到不属于自己的属性。</p><h3 id="实例对象的-proto-如何产生的"><a href="#实例对象的-proto-如何产生的" class="headerlink" title="实例对象的 _proto_ 如何产生的"></a>实例对象的 <code>_proto_</code> 如何产生的</h3><p>从上图可知,当我们使用 <code>new</code> 操作符时,生成的实例对象拥有了 <code>_proto_</code>属性。</p><pre><code>function Foo() {}// 这个函数是 Function 的实例对象// function 就是一个语法糖// 内部调用了 new Function(...)</code></pre><p>所以可以说,在 <code>new</code> 的过程中,新对象被添加了 <code>_proto_</code> 并且链接到构造函数的原型上。</p><h3 id="new-的过程"><a href="#new-的过程" class="headerlink" title="new 的过程"></a>new 的过程</h3><ol><li>新生成了一个对象</li><li>链接到原型</li><li>绑定 this</li><li>返回新对象</li></ol><p>在调用 <code>new</code> 的过程中会发生以上四件事情,我们也可以试着来自己实现一个 <code>new</code></p><pre><code>function create() { // 创建一个空的对象 let obj = new Object() // 获得构造函数 let Con = [].shift.call(arguments) // 链接到原型 obj.__proto__ = Con.prototype // 绑定 this,执行构造函数 let result = Con.apply(obj, arguments) // 确保 new 出来的是个对象 return typeof result === 'object' ? result : obj}</code></pre><p>对于实例对象来说,都是通过 <code>new</code> 产生的,无论是 <code>function Foo()</code> 还是 <code>let a = { b : 1 }</code> 。</p><p>对于创建一个对象来说,更推荐使用字面量的方式创建对象。因为你使用 <code>new Object()</code> 的方式创建对象需要通过作用域链一层层找到 <code>Object</code>,但是你使用字面量的方式就没这个问题。</p><pre><code>function Foo() {}// function 就是个语法糖// 内部等同于 new Function()let a = { b: 1 }// 这个字面量内部也是使用了 new Object()</code></pre><h2 id="Function-proto-Function-prototype"><a href="#Function-proto-Function-prototype" class="headerlink" title="Function.proto === Function.prototype"></a>Function.<strong>proto</strong> === Function.prototype</h2><p>对于对象来说,<code>xx.__proto__.contrcutor</code> 是该对象的构造函数,但是在图中我们可以发现 <code>Function.__proto__ === Function.prototype</code>,难道这代表着 <code>Function</code> 自己产生了自己?</p><p>答案肯定是否认的,要说明这个问题我们先从 <code>Object</code> 说起。</p><p>从图中我们可以发现,所有对象都可以通过原型链最终找到 <code>Object.prototype</code> ,虽然 <code>Object.prototype</code> 也是一个对象,但是这个对象却不是 <code>Object</code> 创造的,而是引擎自己创建了 <code>Object.prototype</code> 。<strong>所以可以这样说,所有实例都是对象,但是对象不一定都是实例。</strong></p><p>接下来我们来看 <code>Function.prototype</code> 这个特殊的对象,如果你在浏览器将这个对象打印出来,会发现这个对象其实是一个函数。</p><p>我们知道函数都是通过 <code>new Function()</code> 生成的,难道 <code>Function.prototype</code> 也是通过 <code>new Function()</code> 产生的吗?答案也是否定的,这个函数也是引擎自己创建的。首先引擎创建了 <code>Object.prototype</code> ,然后创建了 <code>Function.prototype</code> ,并且通过 <code>__proto__</code> 将两者联系了起来。这里也很好的解释了上面的一个问题,为什么 <code>let fun = Function.prototype.bind()</code> 没有 <code>prototype</code> 属性。因为 <code>Function.prototype</code> 是引擎创建出来的对象,引擎认为不需要给这个对象添加 <code>prototype</code> 属性。</p><p><strong>所以我们又可以得出一个结论,不是所有函数都是 <code>new Function()</code> 产生的。</strong></p><p>有了 <code>Function.prototype</code> 以后才有了 <code>function Function()</code> ,然后其他的构造函数都是 <code>function Function()</code> 生成的。</p><p>现在可以来解释 <code>Function.__proto__ === Function.prototype</code> 这个问题了。因为先有的 <code>Function.prototype</code> 以后才有的 <code>function Function()</code> ,所以也就不存在鸡生蛋蛋生鸡的悖论问题了。对于为什么 <code>Function.__proto__</code> 会等于 <code>Function.prototype</code> ,个人的理解是:其他所有的构造函数都可以通过原型链找到 <code>Function.prototype</code> ,并且 <code>function Function()</code> 本质也是一个函数,为了不产生混乱就将 <code>function Function()</code> 的 <code>__proto__</code> 联系到了 <code>Function.prototype</code> 上。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li><code>Object</code> 是所有对象的爸爸,所有对象都可以通过 <code>__proto__</code> 找到它</li><li><code>Function</code> 是所有函数的爸爸,所有函数都可以通过 <code>__proto__</code> 找到它</li><li><code>Function.prototype</code> 和 <code>Object.prototype</code> 是两个特殊的对象,他们由引擎来创建</li><li>除了以上两个特殊对象,其他对象都是通过构造器 <code>new</code> 出来的</li><li>函数的 <code>prototype</code> 是一个对象,也就是原型</li><li>对象的 <code>__proto__</code> 指向原型, <code>__proto__</code> 将对象和原型连接起来组成了原型链</li></ul>]]></content>
<summary type="html">
<p>本文不会过多介绍基础知识,而是把重点放在原型的各个难点上。</p>
<p><img src="-a7f68c7b-187a-4c44-9718-18fa861b841f1621e8a9bcb0872d" alt=""></p>
<p>大家可以先仔细分析下该图,然后让我们进入
</summary>
<category term="前端" scheme="https://blog.yanng.io/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>深度解析 Vue 响应式原理</title>
<link href="https://blog.yanng.io/2018/10/20/%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90%20Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/"/>
<id>https://blog.yanng.io/2018/10/20/%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90%20Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/</id>
<published>2018-10-20T14:43:57.000Z</published>
<updated>2019-02-27T15:33:06.000Z</updated>
<content type="html"><![CDATA[<h2 id="Vue-初始化"><a href="#Vue-初始化" class="headerlink" title="Vue 初始化"></a>Vue 初始化</h2><p>在 Vue 的初始化中,会先对 props 和 data 进行初始化</p><pre><code>Vue.prototype._init = function(options?: Object) { // ... // 初始化 props 和 data initState(vm) initProvide(vm) callHook(vm, 'created') if (vm.$options.el) { // 挂载组件 vm.$mount(vm.$options.el) }}</code></pre><p>接下来看下如何初始化 props 和 data</p><pre><code>export function initState(vm: Component) { // 初始化 props if (opts.props) initProps(vm, opts.props) if (opts.data) { // 初始化 data initData(vm) }}function initProps(vm: Component, propsOptions: Object) { const propsData = vm.$options.propsData || {} const props = (vm._props = {}) // 缓存 key const keys = (vm.$options._propKeys = []) const isRoot = !vm.$parent // 非根组件的 props 不需要观测 if (!isRoot) { toggleObserving(false) } for (const key in propsOptions) { keys.push(key) // 验证 prop const value = validateProp(key, propsOptions, propsData, vm) // 通过 defineProperty 函数实现双向绑定 defineReactive(props, key, value) // 可以让 vm._props.x 通过 vm.x 访问 if (!(key in vm)) { proxy(vm, `_props`, key) } } toggleObserving(true)}function initData(vm: Component) { let data = vm.$options.data data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {} if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== 'production' && warn( 'data functions should return an object:\n' + 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm ) } // proxy data on instance const keys = Object.keys(data) const props = vm.$options.props const methods = vm.$options.methods let i = keys.length while (i--) { const key = keys[i] if (props && hasOwn(props, key)) { } else if (!isReserved(key)) { // 可以让 vm._data.x 通过 vm.x 访问 proxy(vm, `_data`, key) } } // 监听 data observe(data, true /* asRootData */)}export function observe(value: any, asRootData: ?boolean): Observer | void { // 如果 value 不是对象或者使 VNode 类型就返回 if (!isObject(value) || value instanceof VNode) { return } let ob: Observer | void // 使用缓存的对象 if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__ } else if ( shouldObserve && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { // 创建一个监听者 ob = new Observer(value) } if (asRootData && ob) { ob.vmCount++ } return ob}export class Observer { value: any dep: Dep vmCount: number // number of vms that has this object as root $data constructor(value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 // 通过 defineProperty 为对象添加 __ob__ 属性,并且配置为不可枚举 // 这样做的意义是对象遍历时不会遍历到 __ob__ 属性 def(value, '__ob__', this) // 判断类型,不同的类型不同处理 if (Array.isArray(value)) { // 判断数组是否有原型 // 在该处重写数组的一些方法,因为 Object.defineProperty 函数 // 对于数组的数据变化支持的不好,这部分内容会在下面讲到 const augment = hasProto ? protoAugment : copyAugment augment(value, arrayMethods, arrayKeys) this.observeArray(value) } else { this.walk(value) } } // 遍历对象,通过 defineProperty 函数实现双向绑定 walk(obj: Object) { const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i]) } } // 遍历数组,对每一个元素进行观测 observeArray(items: Array<any>) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) } }}</code></pre><h2 id="Object-defineProperty"><a href="#Object-defineProperty" class="headerlink" title="Object.defineProperty"></a>Object.defineProperty</h2><p>无论是对象还是数组,需要实现双向绑定的话最终都会执行这个函数,该函数可以监听到 <code>set</code> 和 <code>get</code> 的事件。</p><pre><code>export function defineReactive( obj: Object, key: string, val: any, customSetter?: ?Function, shallow?: boolean) { // 创建依赖实例,通过闭包的方式让 // set get 函数使用 const dep = new Dep() // 获得属性对象 const property = Object.getOwnPropertyDescriptor(obj, key) if (property && property.configurable === false) { return } // 获取自定义的 getter 和 setter const getter = property && property.get const setter = property && property.set if ((!getter || setter) && arguments.length === 2) { val = obj[key] } // 如果 val 是对象的话递归监听 let childOb = !shallow && observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, // 拦截 getter,当取值时会触发该函数 get: function reactiveGetter() { const value = getter ? getter.call(obj) : val // 进行依赖收集 // 初始化时会在初始化渲染 Watcher 时访问到需要双向绑定的对象 // 从而触发 get 函数 if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }, // 拦截 setter,当赋值时会触发该函数 set: function reactiveSetter(newVal) { const value = getter ? getter.call(obj) : val // 判断值是否发生变化 if (newVal === value || (newVal !== newVal && value !== value)) { return } if (process.env.NODE_ENV !== 'production' && customSetter) { customSetter() } if (setter) { setter.call(obj, newVal) } else { val = newVal } // 如果新值是对象的话递归监听 childOb = !shallow && observe(newVal) // 派发更新 dep.notify() }, })}</code></pre><p>在 <code>Object.defineProperty</code> 中自定义 <code>get</code> 和 <code>set</code> 函数,并在 <code>get</code> 中进行依赖收集,在 <code>set</code> 中派发更新。接下来我们先看如何进行依赖收集。</p><h2 id="依赖收集"><a href="#依赖收集" class="headerlink" title="依赖收集"></a>依赖收集</h2><p>依赖收集是通过 <code>Dep</code> 来实现的,但是也与 Watcher 息息相关</p><pre><code>export default class Dep { static target: ?Watcher; id: number; subs: Array<Watcher>; constructor () { this.id = uid++ this.subs = [] } // 添加观察者 addSub (sub: Watcher) { this.subs.push(sub) } // 移除观察者 removeSub (sub: Watcher) { remove(this.subs, sub) } depend () { if (Dep.target) {、 // 调用 Watcher 的 addDep 函数 Dep.target.addDep(this) } } // 派发更新 notify () { const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() } }}// 同一时间只有一个观察者使用,赋值观察者Dep.target = null</code></pre><p>对于 Watcher 来说,分为两种 Watcher,分别为渲染 Watcher 和用户写的 Watcher。渲染 Watcher 是在初始化中实例化的。</p><pre><code>export function mountComponent( vm: Component, el: ?Element, hydrating?: boolean): Component { // ... let updateComponent if (process.env.NODE_ENV !== 'production' && config.performance && mark) { } else { // 组件渲染,该回调会在初始化和数据变化时调用 updateComponent = () => { vm._update(vm._render(), hydrating) } } // 实例化渲染 Watcher new Watcher( vm, updateComponent, noop, { before() { if (vm._isMounted) { callHook(vm, 'beforeUpdate') } }, }, true /* isRenderWatcher */ ) return vm}</code></pre><p>接下来看一下 Watcher 的部分实现</p><pre><code>export default class Watcher { constructor( vm: Component, expOrFn: string | Function, cb: Function, options?: ?Object, isRenderWatcher?: boolean ) { // ... if (this.computed) { this.value = undefined this.dep = new Dep() } else { this.value = this.get() } } get() { // 该函数用于缓存 Watcher // 因为在组件含有嵌套组件的情况下,需要恢复父组件的 Watcher pushTarget(this) let value const vm = this.vm try { // 调用回调函数,也就是 updateComponent 函数 // 在这个函数中会对需要双向绑定的对象求值,从而触发依赖收集 value = this.getter.call(vm, vm) } catch (e) { if (this.user) { handleError(e, vm, `getter for watcher "${this.expression}"`) } else { throw e } } finally { // "touch" every property so they are all tracked as // dependencies for deep watching if (this.deep) { traverse(value) } // 恢复 Watcher popTarget() // 清理依赖,判断是否还需要某些依赖,不需要的清除 // 这是为了性能优化 this.cleanupDeps() } return value } // 在依赖收集中调用 addDep(dep: Dep) { const id = dep.id if (!this.newDepIds.has(id)) { this.newDepIds.add(id) this.newDeps.push(dep) if (!this.depIds.has(id)) { // 调用 Dep 中的 addSub 函数 // 将当前 Watcher push 进数组 dep.addSub(this) } } }}export function pushTarget(_target: ?Watcher) { // 设置全局的 target if (Dep.target) targetStack.push(Dep.target) Dep.target = _target}export function popTarget() { Dep.target = targetStack.pop()}</code></pre><p>以上就是依赖收集的全过程。核心流程是先对配置中的 props 和 data 中的每一个值调用 <code>Obeject.defineProperty()</code> 来拦截 <code>set</code> 和 <code>get</code> 函数,再在渲染 Watcher 中访问到模板中需要双向绑定的对象的值触发依赖收集。</p><h2 id="派发更新"><a href="#派发更新" class="headerlink" title="派发更新"></a>派发更新</h2><p>改变对象的数据时,会触发派发更新,调用 <code>Dep</code> 的 <code>notify</code> 函数</p><pre><code>notify () { // 执行 Watcher 的 update const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() }}update () { if (this.computed) { // ... } else if (this.sync) { // ... } else { // 一般会进入这个条件 queueWatcher(this) }}export function queueWatcher(watcher: Watcher) {// 获得 id const id = watcher.id // 判断 Watcher 是否 push 过 // 因为存在改变了多个数据,多个数据的 Watch 是同一个 if (has[id] == null) { has[id] = true if (!flushing) { // 最初会进入这个条件 queue.push(watcher) } else { // 在执行 flushSchedulerQueue 函数时,如果有新的派发更新会进入这里 // 插入新的 watcher let i = queue.length - 1 while (i > index && queue[i].id > watcher.id) { i-- } queue.splice(i + 1, 0, watcher) } // 最初会进入这个条件 if (!waiting) { waiting = true // 将所有 Watcher 统一放入 nextTick 调用 // 因为每次派发更新都会引发渲染 nextTick(flushSchedulerQueue) } }}function flushSchedulerQueue() { flushing = true let watcher, id // 根据 id 排序 watch,确保如下条件 // 1. 组件更新从父到子 // 2. 用户写的 Watch 先于渲染 Watch // 3. 如果在父组件 watch run 的时候有组件销毁了,这个 Watch 可以被跳过 queue.sort((a, b) => a.id - b.id) // 不缓存队列长度,因为在遍历的过程中可能队列的长度发生变化 for (index = 0; index < queue.length; index++) { watcher = queue[index] if (watcher.before) { // 执行 beforeUpdate 钩子函数 watcher.before() } id = watcher.id has[id] = null // 在这里执行用户写的 Watch 的回调函数并且渲染组件 watcher.run() // 判断无限循环 // 比如在 watch 中又重新给对象赋值了,就会出现这个情况 if (process.env.NODE_ENV !== 'production' && has[id] != null) { circular[id] = (circular[id] || 0) + 1 if (circular[id] > MAX_UPDATE_COUNT) { warn( 'You may have an infinite update loop ' + (watcher.user ? `in watcher with expression "${watcher.expression}"` : `in a component render function.`), watcher.vm ) break } } } // ...}</code></pre><p>以上就是派发更新的全过程。核心流程就是给对象赋值,触发 <code>set</code> 中的派发更新函数。将所有 Watcher 都放入 <code>nextTick</code> 中进行更新,<code>nextTick</code> 回调中执行用户 Watch 的回调函数并且渲染组件。</p><h2 id="Object-defineProperty-的缺陷"><a href="#Object-defineProperty-的缺陷" class="headerlink" title="Object.defineProperty 的缺陷"></a>Object.defineProperty 的缺陷</h2><p>以上已经分析完了 Vue 的响应式原理,接下来说一点 <code>Object.defineProperty</code> 中的缺陷。</p><p>如果通过下标方式修改数组数据或者给对象新增属性并不会触发组件的重新渲染,因为 <code>Object.defineProperty</code> 不能拦截到这些操作,更精确的来说,对于数组而言,大部分操作都是拦截不到的,只是 Vue 内部通过重写函数的方式解决了这个问题。</p><p>对于第一个问题,Vue 提供了一个 API 解决</p><pre><code>export function set(target: Array<any> | Object, key: any, val: any): any { // 判断是否为数组且下标是否有效 if (Array.isArray(target) && isValidArrayIndex(key)) { // 调用 splice 函数触发派发更新 // 该函数已被重写 target.length = Math.max(target.length, key) target.splice(key, 1, val) return val } // 判断 key 是否已经存在 if (key in target && !(key in Object.prototype)) { target[key] = val return val } const ob = (target: any).__ob__ if (target._isVue || (ob && ob.vmCount)) { process.env.NODE_ENV !== 'production' && warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ) return val } // 如果对象不是响应式对象,就赋值返回 if (!ob) { target[key] = val return val } // 进行双向绑定 defineReactive(ob.value, key, val) // 手动派发更新 ob.dep.notify() return val}</code></pre><p>对于数组而言,Vue 内部重写了以下函数实现派发更新</p><pre><code>// 获得数组原型const arrayProto = Array.prototypeexport const arrayMethods = Object.create(arrayProto)// 重写以下函数const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse',]methodsToPatch.forEach(function(method) { // 缓存原生函数 const original = arrayProto[method] // 重写函数 def(arrayMethods, method, function mutator(...args) { // 先调用原生函数获得结果 const result = original.apply(this, args) const ob = this.__ob__ let inserted // 调用以下几个函数时,监听新数据 switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) // 手动派发更新 ob.dep.notify() return result })})</code></pre>]]></content>
<summary type="html">
<h2 id="Vue-初始化"><a href="#Vue-初始化" class="headerlink" title="Vue 初始化"></a>Vue 初始化</h2><p>在 Vue 的初始化中,会先对 props 和 data 进行初始化</p>
<pre><code>
</summary>
<category term="前端" scheme="https://blog.yanng.io/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>JavaScript面试题/考点/解答(持续更新中...)</title>
<link href="https://blog.yanng.io/2018/08/13/js%E5%9F%BA%E7%A1%80%E9%9D%A2%E8%AF%95%E9%A2%98-%E9%A2%98%E7%9B%AE-%E8%80%83%E7%82%B9-%E8%A7%A3%E7%AD%94%E6%89%8B%E8%AE%B0/"/>
<id>https://blog.yanng.io/2018/08/13/js%E5%9F%BA%E7%A1%80%E9%9D%A2%E8%AF%95%E9%A2%98-%E9%A2%98%E7%9B%AE-%E8%80%83%E7%82%B9-%E8%A7%A3%E7%AD%94%E6%89%8B%E8%AE%B0/</id>
<published>2018-08-13T06:32:51.000Z</published>
<updated>2018-09-01T08:58:14.000Z</updated>
<content type="html"><![CDATA[<h2 id="变量类型和计算"><a href="#变量类型和计算" class="headerlink" title="变量类型和计算"></a>变量类型和计算</h2><h3 id="题目:"><a href="#题目:" class="headerlink" title="题目:"></a>题目:</h3><ul><li>js中使用typeof能得到哪些类型</li><li>何时使用 === 何时使用 ==</li><li>js中有哪些内置函数</li><li>js中变量按照存储方式区分为哪些类型,并描述其特点</li><li>如何理解JSON</li></ul><h3 id="考点:"><a href="#考点:" class="headerlink" title="考点:"></a>考点:</h3><h4 id="值类型vs引用类型"><a href="#值类型vs引用类型" class="headerlink" title="值类型vs引用类型"></a>值类型vs引用类型</h4><p>eg.<br>值类型:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var a = 100</span><br><span class="line">''var b = a</span><br><span class="line">''a = 200</span><br><span class="line">''console.log(b) </span><br><span class="line">//100</span><br></pre></td></tr></table></figure><p>引用类型:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var a = {age:20}</span><br><span class="line">var b = a</span><br><span class="line">b.age = 21</span><br><span class="line">console.log(a.age) </span><br><span class="line">//21</span><br></pre></td></tr></table></figure><h4 id="typeof-运算符详解"><a href="#typeof-运算符详解" class="headerlink" title="typeof 运算符详解"></a>typeof 运算符详解</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">typeof undefined //undefined</span><br><span class="line">typeof `'abc'` //string</span><br><span class="line">typeof 123 //bumber</span><br><span class="line">typeof true //boolean</span><br><span class="line">typeof `{}` //object</span><br><span class="line">typeof `[]` //object(array)</span><br><span class="line">typeof null //object</span><br><span class="line">typeof console.log //function</span><br></pre></td></tr></table></figure><h4 id="变量计算-强制类型转换"><a href="#变量计算-强制类型转换" class="headerlink" title="变量计算 - 强制类型转换"></a>变量计算 - 强制类型转换</h4><ul><li>字符串拼接</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var a = 100 + 10 //110</span><br><span class="line">var b =100 + '10' //'10010'</span><br></pre></td></tr></table></figure><ul><li>==运算符</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">100 == '100' //true</span><br><span class="line">0 == ' ' //true</span><br><span class="line">null == undefined //true</span><br></pre></td></tr></table></figure><ul><li>if语句</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">var a = true </span><br><span class="line">if(a){</span><br><span class="line">//.....</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">var b =100</span><br><span class="line">if(b){</span><br><span class="line">//.....</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">var c = ' '</span><br><span class="line">if(c){</span><br><span class="line">//.....</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>逻辑运算</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">console.log(10&&0) //0</span><br><span class="line">console.log(' '||'abc') //'abc'</span><br><span class="line">console.log(!window.abc) //true</span><br><span class="line">//判断一个变量会被当做 true 还是 false</span><br><span class="line">var a = 100</span><br><span class="line">console.log(!!a)</span><br></pre></td></tr></table></figure><h3 id="解答:"><a href="#解答:" class="headerlink" title="解答:"></a>解答:</h3><ul><li><p>js中使用typeof能得到哪些类型?<br>如上。</p></li><li><p>何时使用 === 何时使用 ==<br> if (obj.a==null){<br> //这里是相当于obj.a===null || obj.a === undefined,简写形式<br> //这是jquery源码中推荐的写法<br> }</p></li><li><p>js中有哪些内置函数——数据封装类对象</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Object</span><br><span class="line">Array</span><br><span class="line">Boolean</span><br><span class="line">Number</span><br><span class="line">String</span><br><span class="line">Function</span><br><span class="line">Data</span><br><span class="line">RegExp</span><br><span class="line">Error</span><br></pre></td></tr></table></figure><ul><li>js中变量按照存储方式区分为哪些类型,并描述其特点</li></ul><ol><li>值类型(单纯赋值)</li><li>引用类型(指针指向)<br>特点:如上。</li></ol><ul><li>如何理解JSON<br>只不过是一个JS对象而已</li></ul><p>对象转化成字符串:<br> JSON.stringify({a:10,b:20})<br>字符串转化成对象:<br> JSON.parse(‘{“a”:10,”b”:20}’)</p>]]></content>
<summary type="html">
<h2 id="变量类型和计算"><a href="#变量类型和计算" class="headerlink" title="变量类型和计算"></a>变量类型和计算</h2><h3 id="题目:"><a href="#题目:" class="headerlink" title=
</summary>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>前端面试题考点汇总</title>
<link href="https://blog.yanng.io/2018/08/03/%E7%89%9B%E5%AE%A2%E9%9D%A2%E8%AF%95%E9%A2%98%E6%89%8B%E8%AE%B0/"/>
<id>https://blog.yanng.io/2018/08/03/%E7%89%9B%E5%AE%A2%E9%9D%A2%E8%AF%95%E9%A2%98%E6%89%8B%E8%AE%B0/</id>
<published>2018-08-03T06:32:51.000Z</published>
<updated>2018-09-01T08:54:46.000Z</updated>
<content type="html"><![CDATA[<h2 id="选择器"><a href="#选择器" class="headerlink" title="选择器"></a>选择器</h2><h4 id="子选择器和后代选择器:"><a href="#子选择器和后代选择器:" class="headerlink" title="子选择器和后代选择器:"></a>子选择器和后代选择器:</h4><blockquote><p>子选择器:(>)<br>后代选择器:(空格)</p></blockquote><p>区别:> 作用于元素的第一代后代,空格作用于元素的所有后代。</p><h4 id="属性选择器"><a href="#属性选择器" class="headerlink" title="属性选择器"></a>属性选择器</h4><p><code>(a[rel = "external"])</code></p><h4 id="相邻选择器"><a href="#相邻选择器" class="headerlink" title="相邻选择器"></a>相邻选择器</h4><p>(h1 + p)</p><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h4 id="可继承的样式:"><a href="#可继承的样式:" class="headerlink" title="可继承的样式:"></a>可继承的样式:</h4><ol><li><p>font-size</p></li><li><p>font-family</p></li><li><p>color</p></li><li><p>text-indent</p></li></ol><h4 id="不可继承的样式:"><a href="#不可继承的样式:" class="headerlink" title="不可继承的样式:"></a>不可继承的样式:</h4><ol><li><p>border</p></li><li><p>padding</p></li><li><p>margin</p></li><li><p>width</p></li><li><p>height</p></li></ol><h4 id="优先级算法:"><a href="#优先级算法:" class="headerlink" title="优先级算法:"></a>优先级算法:</h4><ol><li><p>优先级就近原则,同权重情况下样式定义最近者为准;</p></li><li><p>载入样式以最后载入的定位为准;</p></li><li><p>!important > id > class > tag </p></li><li><p>important 比 内联优先级高,但内联比 id 要高</p></li></ol><h4 id="CSS3-新增伪类举例:"><a href="#CSS3-新增伪类举例:" class="headerlink" title="CSS3 新增伪类举例:"></a>CSS3 新增伪类举例:</h4><ul><li><p>p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。</p></li><li><p>p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。</p></li><li><p>p:only-of-type 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。</p></li><li><p>p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。</p></li><li><p>p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。</p></li><li><p>:enabled :disabled 控制表单控件的禁用状态。</p></li><li><p>:checked 单选框或复选框被选中。</p></li></ul><h2 id="display-的值及作用:"><a href="#display-的值及作用:" class="headerlink" title="display 的值及作用:"></a>display 的值及作用:</h2><ol><li><p>block</p></li><li><p>inline-block</p></li><li><p>inline</p></li><li><p>list-item 象块类型元素一样显示,并添加样式列表标记。</p></li><li><p>none:隐藏元素,在页面中不占据空间</p></li></ol><h2 id="position-的值的定位区别:"><a href="#position-的值的定位区别:" class="headerlink" title="position 的值的定位区别:"></a>position 的值的定位区别:</h2><ol><li><p>absolute 生成绝对定位的元素,相对于 static 定位以外的第一个祖先元素进行定位。</p></li><li><p>fixed 生成固定定位的元素,相对于浏览器窗口进行定位(老 IE 不支持)。</p></li><li><p>relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。</p></li><li><p>static 默认值(静态)。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。</p></li><li><p>inherit 规定从父元素继承 position 属性的值。</p></li></ol><h2 id="css3新特性"><a href="#css3新特性" class="headerlink" title="css3新特性"></a>css3新特性</h2><ol><li><p>CSS3 实现圆角(border-radius),阴影(box-shadow)</p></li><li><p>对文字加特效(text-shadow、),线性渐变(gradient),转换(transform)</p></li><li><p>transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);// 旋转, 缩放, 定位, 倾斜</p></li><li><p>增加了更多的 CSS 选择器 多背景 rgba</p></li><li><p>在 CSS3 中唯一引入的伪类是 ::selection.</p></li><li><p>媒体查询,多栏布局</p></li><li><p>border-image</p></li></ol><h3 id="转换-transform"><a href="#转换-transform" class="headerlink" title="转换(transform)"></a>转换(transform)</h3><ol><li>平移</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">transform:translateX(-30px); 水平方向 左右,负正</span><br><span class="line"></span><br><span class="line">transform:translateY(-30px); 垂直方向 正上;负下</span><br><span class="line"></span><br><span class="line">transform:translate(-30px,30px); 斜</span><br></pre></td></tr></table></figure><ol start="2"><li>旋转 :角度</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">transform:rotate (180deg)</span><br></pre></td></tr></table></figure><ol start="3"><li>缩放:倍数</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">transform:scale</span><br><span class="line"></span><br><span class="line">transform:scaleX</span><br><span class="line"></span><br><span class="line">transform:scaleY</span><br></pre></td></tr></table></figure><ol start="4"><li>斜切:角度</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">transform:skew</span><br><span class="line"></span><br><span class="line">transform:skewX</span><br><span class="line"></span><br><span class="line">transform:skewY</span><br></pre></td></tr></table></figure><ol start="5"><li>过度:对运动过程进行控制</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">transition;all 2s 1s ease;</span><br><span class="line"></span><br><span class="line">属性名称 持续时间 延迟 运动方式(贝塞尔曲线)</span><br></pre></td></tr></table></figure><ol start="6"><li>阴影</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">box-shadow: 0px 0px 10px 10px rgba(0,0,0,0.4)</span><br></pre></td></tr></table></figure><p>第一个参数:水平方向 正 右; 负 左; 0 左右</p><p>第二个参数: 垂直方向 正上 ; 负下 ; 0 上下</p><p>第三个参数: 迷糊程度 值越大越模糊</p><p>第四个参数:阴影大小</p><p>第五个参数: 阴影颜色</p><p>第六个参数: 内阴影 inset;</p><ol start="7"><li>文本阴影</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">text-shadow: 5px 5px 5px #FF0000;</span><br></pre></td></tr></table></figure><h3 id="边框图片"><a href="#边框图片" class="headerlink" title="边框图片"></a>边框图片</h3><p>引入图片:<br><code>boder-image-source:url('');</code></p><p>设置边框图片的宽度:<br><code>boder-image-width:20px;</code></p><p>切片 九个区域 四个角 四个边 中间 fill:<br><code>boder-image-slice:45;</code></p><p>重复:<br>stretch 拉伸(默认)<br>repeat 重复(不完整)<br>round 重复(完整)<br><code>boder-image-repeat:round;</code></p><h3 id="渐变"><a href="#渐变" class="headerlink" title="渐变"></a>渐变</h3><h4 id="线性渐变"><a href="#线性渐变" class="headerlink" title="线性渐变"></a>线性渐变</h4><p>添加属性:background-image<br><code>linear-gradient(top,red,yellow);</code><br>第一参数:渐变开始的方向<br>第二参数:开始的颜色<br>第三参数:结束的颜色<br>颜色:关键字,十六进制,rgb,rgba<br>方向:关键字 left top bottom right<br>角度: 0deg<br>均匀的线性渐变<br>不均匀的线形渐变:(百分比 纯色)<br><code>linear-gradient(top,red 30%,yellow);</code><br>重复性渐变:<br><code>repeating-linear-gradient(top,red,yellow 20%);</code></p><h4 id="径向渐变"><a href="#径向渐变" class="headerlink" title="径向渐变"></a>径向渐变</h4><p>添加属性:background-image<br><code>radial-gradient(at 30px 30px,red,yellow);</code><br>第一参数:中心点位置<br>第二参数:开始的颜色<br>第三参数:结束的颜色<br>不均匀径向渐变<br>重复性径向渐变:<br><code>repeating-gradial-gradient(red,yellow 20%);</code></p><h3 id="文本修饰(下划线等)"><a href="#文本修饰(下划线等)" class="headerlink" title="文本修饰(下划线等)"></a>文本修饰(下划线等)</h3><p>上划线:<code>h1 {text-decoration:overline}</code><br>删除线:<code>h2 {text-decoration:line-through}</code><br>下划线:<code>h3 {text-decoration:underline}</code><br>(不支持IE,Chrome,Safari):<code>h4 {text-decoration:blink}</code></p><h2 id="对BFC规范的理解"><a href="#对BFC规范的理解" class="headerlink" title="对BFC规范的理解"></a>对BFC规范的理解</h2><p>块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。</p><p>BFC,块级格式化上下文,一个创建了新的 BFC 的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个 BFC 中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的 margin 会发生折叠。</p><p>W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行布局,以及与其他元素的关系和相互作用。</p><h2 id="CSS-sprites"><a href="#CSS-sprites" class="headerlink" title="CSS sprites"></a>CSS sprites</h2><p>CSS Sprites 其实就是把网页中一些背景图片整合到一张图片文件中,再利用 CSS 的 “background-image”,”background-repeat”,”background-position” 的组合进行背景定位,background-position 可以用数字能精确的定位出背景图片的位置。这样可以减少很多图片请求的开销,因为请求耗时比较长;请求虽然可以并发,但是也有限制,一般浏览器都是 6 个。对于未来而言,就不需要这样做了,因为有了 http2。</p><h2 id="DOCTYPE"><a href="#DOCTYPE" class="headerlink" title="DOCTYPE"></a>DOCTYPE</h2><ol><li><!DOCTYPE> 声明位于文档中的最前面,处于 <html> 标签之前。告知浏览器以何种模式来渲染文档。 </li><li>严格模式的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。</li><li>在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。</li><li>DOCTYPE 不存在或格式不正确会导致文档以混杂模式呈现。 <h4 id="DOCTYPE类型"><a href="#DOCTYPE类型" class="headerlink" title="DOCTYPE类型"></a>DOCTYPE类型</h4></li><li>该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。</li><li>HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。</li><li>XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。</li><li>Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。</li></ol><h2 id="HTML-与-XHTML"><a href="#HTML-与-XHTML" class="headerlink" title="HTML 与 XHTML"></a>HTML 与 XHTML</h2><p>最主要的不同:<br>XHTML 元素必须被正确地嵌套。<br>XHTML 元素必须被关闭。<br>标签名必须用小写字母。<br>XHTML 文档必须拥有根元素。</p><h2 id="html-常见兼容性问题"><a href="#html-常见兼容性问题" class="headerlink" title="html 常见兼容性问题"></a>html 常见兼容性问题</h2><ol><li><p>png24 位的图片在 iE6 浏览器上出现背景<br>解决方案:做成 PNG8,也可以引用一段脚本处理.</p></li><li><p>浏览器默认的 margin 和 padding 不同<br>解决方案:加一个全局的 <code>margin:0;padding:0;</code> 来统一。</p></li><li><p>IE6 双边距 bug:在 IE6 下,如果对元素设置了浮动,同时又设置了 margin-left 或 margin-right,margin 值会加倍。<br><code>box float:left; width:10px; margin:0 0 0 10px;</code><br>这种情况之下 IE 会产生 20px 的距离<br>解决方案:在 float 的标签样式控制中加入 _display:inline; 将其转化为行内属性。( _ 这个符号只有 ie6 会识别)</p></li><li><p>渐进识别的方式,从总体中逐渐排除局部。<br>首先,巧妙的使用 “\9” 这一标记,将 IE 游览器从所有情况中分离出来。<br>接着,再次使用 “+” 将 IE8 和 IE7、IE6 分离开来,这样 IE8 已经独立识别。</p></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.bb{</span><br><span class="line"> background-color:#f1ee18; /所有识别/</span><br><span class="line"> .background-color:#00deff\9; /IE6、7、8识别/</span><br><span class="line"> +background-color:#a200ff; /IE6、7识别/</span><br><span class="line"> background-color:#1e0bd1; /IE6识别/ </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>5.IE 下,可以使用获取常规属性的方法来获取自定义属性,也可以使用 getAttribute() 获取自定义属性;Firefox 下, 只能使用 getAttribute() 获取自定义属性<br>解决方法:统一通过 getAttribute() 获取自定义属性<br>6. IE 下,event 对象有 x、y 属性,但是没有 pageX、pageY 属性; Firefox 下,event 对象有 pageX、pageY 属性,但是没有 x、y 属性<br>解决方法:(条件注释)缺点是在 IE 浏览器下可能会增加额外的 HTTP 请求数。<br>7. Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示<br>解决方法:可通过加入 CSS 属性 <code>-webkit-text-size-adjust: none;</code> 解决<br>8. 超链接访问过后 hover 样式就不出现了,被点击访问过的超链接样式不在具有 hover 和 active 了<br>解决方法:改变 CSS 属性的排列顺序 L-V-H-A</p><p><code>a:link {}</code><br><code>a:visited {}</code><br><code>a:hover {}</code><br><code>a:active {}</code></p><ol start="9"><li><p>怪异模式问题:漏写 DTD 声明,Firefox 仍然会按照标准模式来解析网页,但在 IE 中会触发怪异模式。为避免怪异模式给我们带来不必要的麻烦,最好养成书写 DTD 声明的好习惯。现在可以使用 <a href="">html5</a>(<a href="http://www.w3.org/TR/html5/single-page.html">http://www.w3.org/TR/html5/single-page.html</a>) 推荐的写法:<!DOCTYPE html></p></li><li><p>上下 margin 重合问题:ie 和 ff 都存在,相邻的两个 div 的 margin-left 和 margin-right 不会重合,但是 margin-top 和 margin-bottom 却会发生重合。<br>解决方法:养成良好的代码编写习惯,同时采用 margin-top 或者同时采用 margin-bottom。</p></li><li><p>ie6 对 png 图片格式支持不好<br>解决方案:引用一段脚本处理</p></li></ol><h2 id="清除浮动"><a href="#清除浮动" class="headerlink" title="清除浮动"></a>清除浮动</h2><p>浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。</p><ol><li><p>使用空标签清除浮动。<br>这种方法是在所有浮动标签后面添加一个空标签 定义 css clear:both. 弊端就是增加了无意义标签。</p></li><li><p>使用 overflow。<br>给包含浮动元素的父标签添加 css 属性 overflow:auto; zoom:1; zoom:1 用于兼容 IE6。可以给父元素设置 overflow:auto 或者 hidden。</p></li><li><p>使用 after 伪对象清除浮动。<br>该方法只适用于非 IE 浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;</p></li></ol><h2 id="IE-8-以下版本的浏览器中的盒模型有什么不同"><a href="#IE-8-以下版本的浏览器中的盒模型有什么不同" class="headerlink" title="IE 8 以下版本的浏览器中的盒模型有什么不同"></a>IE 8 以下版本的浏览器中的盒模型有什么不同</h2><p>IE8 以下浏览器的盒模型中定义的元素的宽高包括内边距和边框</p><h2 id="DOM-操作——怎样添加、移除、移动、复制、创建和查找节点。"><a href="#DOM-操作——怎样添加、移除、移动、复制、创建和查找节点。" class="headerlink" title="DOM 操作——怎样添加、移除、移动、复制、创建和查找节点。"></a>DOM 操作——怎样添加、移除、移动、复制、创建和查找节点。</h2><ol><li><p>创建新节点<br><code>createDocumentFragment() // 创建一个DOM片段</code><br><code>createElement() // 创建一个具体的元素</code><br><code>createTextNode() // 创建一个文本节点</code></p></li><li><p>添加、移除、替换、插入<br><code>appendChild()</code><br><code>removeChild()</code><br><code>replaceChild()</code><br><code>insertBefore() // 在已有的子节点前插入一个新的子节点</code></p></li><li><p>查找<br><code>getElementsByTagName() // 通过标签名称</code><br><code>getElementsByName() // 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)</code><br><code>getElementById() // 通过元素Id,唯一性</code></p></li></ol><h2 id="html5-有哪些新特性、移除了那些元素?如何处理-HTML5-新标签的浏览器兼容问题?如何区分-HTML-和-HTML5?"><a href="#html5-有哪些新特性、移除了那些元素?如何处理-HTML5-新标签的浏览器兼容问题?如何区分-HTML-和-HTML5?" class="headerlink" title="html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?"></a>html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?</h2><p>新特性:<br>HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。</p><ol><li>拖拽释放 (Drag and drop) API </li><li>语义化更好的内容标签(header,nav,footer,aside,article,section)</li><li>音频、视频 API(audio,video)</li><li>画布 (Canvas) API</li><li>地理 (Geolocation) API</li><li>本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;</li><li>sessionStorage 的数据在浏览器关闭后自动删除</li><li>表单控件,calendar、date、time、email、url、search </li><li>新的技术 webworker, websocket, Geolocation</li></ol><p>移除的元素:</p><ol><li>纯表现的元素:basefont,big,center,font, s,strike,tt,u;</li><li>对可用性产生负面影响的元素:frame,frameset,noframes;</li></ol><p>支持 HTML5 新标签:</p><ol><li>IE8/IE7/IE6 支持通过 document.createElement 方法产生的标签,可以利用这一特性让这些浏览器支持 HTML5 新标签,浏览器支持新标签后,还需要添加标签默认的样式(当然最好的方式是直接使用成熟的框架、使用最多的是 html5shiv 框架):</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><!--[if lt IE 9]> </span><br><span class="line"><script> src="http://html5shiv.googlecode.com/svn/trunk/html5.js"</script> </span><br><span class="line"><![endif]--></span><br></pre></td></tr></table></figure><p>如何区分:<br>DOCTYPE 声明新增的结构元素、功能元素</p><h2 id="iframe-的优缺点?"><a href="#iframe-的优缺点?" class="headerlink" title="iframe 的优缺点?"></a>iframe 的优缺点?</h2><p>优点:</p><ol><li>解决加载缓慢的第三方内容如图标和广告等的加载问题</li><li>Security sandbox</li><li>并行加载脚本</li></ol><p>缺点:</p><ol><li>iframe 会阻塞主页面的 Onload 事件</li><li>即时内容为空,加载也需要时间</li><li>没有语意</li></ol><h2 id="如何实现浏览器内多个标签页之间的通信"><a href="#如何实现浏览器内多个标签页之间的通信" class="headerlink" title="如何实现浏览器内多个标签页之间的通信?"></a>如何实现浏览器内多个标签页之间的通信?</h2><p>使用本地存储方法 </p><ol><li><p>cookie<br>(1)客户端和服务器端都会请求服务器,性能下降<br>(2)存储限制,4kb<br>(3)页面的 cookie 是共享的 </p></li><li><p>storage<br>只是在客户端使用,不会请求服务器处理, 存储量比较大, 只能存储字符串,非字符串的数据在存储之前会被转换为字符串<br>1). sessionStorage </p><pre><code>临时性的,页面打开有,页面关闭没有 数据不共享 </code></pre><p>2).localStorage </p><pre><code>永久性的存储 数据共享 </code></pre><p>3).api </p><pre><code>clear()删除所有值,ff 中没有实现 getItem()根据指定的名字 name 获取对应的值 key(index)获得 index 处的值 removeItem(name)删除由 name 指定的明值对 setItem(name,value)</code></pre></li></ol><h2 id="webSocket-如何兼容低浏览器?"><a href="#webSocket-如何兼容低浏览器?" class="headerlink" title="webSocket 如何兼容低浏览器?"></a>webSocket 如何兼容低浏览器?</h2><p>Adobe Flash Socket 、 ActiveX HTMLFile (IE) 、 基于 multipart 编码发送 XHR 、 基于长轮询的 XHR</p><h2 id="线程与进程的区别"><a href="#线程与进程的区别" class="headerlink" title="线程与进程的区别"></a>线程与进程的区别</h2><p>进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体, 是 CPU 调度和分派的基本单位。</p><ol><li>一个程序至少有一个进程, 一个进程至少有一个线程</li><li>线程的划分尺度小于进程,使得多线程程序的并发性高</li><li>另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率</li><li>线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制 </li><li>从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别</li></ol><h2 id="如何对网站的文件和资源进行优化?"><a href="#如何对网站的文件和资源进行优化?" class="headerlink" title="如何对网站的文件和资源进行优化?"></a>如何对网站的文件和资源进行优化?</h2><p>这道题考察《雅虎军规》</p><ol><li>尽可能减少 http 请求次数,将 css, js, 图片各自合并 </li><li>使用 CDN,降低通信距离 </li><li>添加 Expire/Cache-Control 头 </li><li>启用 Gzip 压缩文件 </li><li>将 css 放在页面最上面 </li><li>将 script 放在页面最下面 </li><li>避免在 css 中使用表达式 </li><li>将 css, js 都放在外部文件中 </li><li>减少 DNS 查询 <ol start="10"><li>最小化 css, js,减小文件体积 </li></ol></li><li>避免重定向 </li><li>移除重复脚本 </li><li>配置实体标签 ETag </li><li>使用 AJAX 缓存,让网站内容分批加载,局部更新</li></ol><h2 id="六种减少页面加载时间的方法"><a href="#六种减少页面加载时间的方法" class="headerlink" title="六种减少页面加载时间的方法"></a>六种减少页面加载时间的方法</h2><ol><li>优化图片 </li><li>图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方) </li><li>优化 CSS(压缩合并 css,如 margin-top, margin-left…) </li><li>网址后加斜杠(如 <a href="http://www.campr.com" target="_blank" rel="noopener">www.campr.com</a> / 目录,会判断这个目录是什么文件类型,或者是目录。) </li><li>标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。<br> 当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了) </li><li>减少 http 请求(合并文件,合并图片)</li></ol><h2 id="你都使用哪些工具来测试代码的性能?(暂弃)"><a href="#你都使用哪些工具来测试代码的性能?(暂弃)" class="headerlink" title="你都使用哪些工具来测试代码的性能?(暂弃)"></a>你都使用哪些工具来测试代码的性能?(暂弃)</h2><ol><li>Profiler</li><li>JSPerf(<a href="http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout)" target="_blank" rel="noopener">http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout)</a></li><li>Dromaeo</li></ol><h2 id="什么是-FOUC(无样式内容闪烁)?你如何来避免-FOUC?"><a href="#什么是-FOUC(无样式内容闪烁)?你如何来避免-FOUC?" class="headerlink" title="什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?"></a>什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?</h2><blockquote><p>FOUC - Flash Of Unstyled Content 文档样式闪烁</p></blockquote><p><code><style type="text/css" media="all">@import "../fouc.css";</style></code><br>而引用 CSS 文件的 @import 就是造成这个问题的罪魁祸首。IE 会先加载整个 HTML 文档的 DOM,然后再去导入外部的 CSS 文件,因此,在页面 DOM 加载完成到 CSS 导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。<br>解决方法简单的出奇,只要在 <head> 之间加入一个 < link > 或者 < script > 元素就可以了。</p>]]></content>
<summary type="html">
<h2 id="选择器"><a href="#选择器" class="headerlink" title="选择器"></a>选择器</h2><h4 id="子选择器和后代选择器:"><a href="#子选择器和后代选择器:" class="headerlink" title=
</summary>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>Hello Hexo!</title>
<link href="https://blog.yanng.io/2018/07/03/hello-hexo/"/>
<id>https://blog.yanng.io/2018/07/03/hello-hexo/</id>
<published>2018-07-03T06:32:51.000Z</published>
<updated>2018-09-01T08:17:00.000Z</updated>
<content type="html"><![CDATA[<a id="more"></a><p>搭建 GitHub + hexo 博客系统,历时两天。</p><p>并且做了全站 https 解析处理,更换 nexT 主题,完成基本配置,绑定七牛云图床等操作。</p><p>至此,hexo建站计划暂时告一段落。今后会利用零散时间将<a href="https://xiaobs.cc" target="_blank" rel="noopener">旧站</a>文章陆续迁移过来,并做一系列完善和优化。</p><p>Yep!</p>]]></content>
<summary type="html">
<a id="more"></a>
<p>搭建 GitHub + hexo 博客系统,历时两天。</p>
<p>并且做了全站 https 解析处理,更换 nexT 主题,完成基本配置,绑定七牛云图床等操作。</p>
<p>至此,hexo建站计划暂时告一段落。今后会利用零散时间将
</summary>
<category term="hexo" scheme="https://blog.yanng.io/tags/hexo/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="https://blog.yanng.io/2018/06/20/hello-world/"/>
<id>https://blog.yanng.io/2018/06/20/hello-world/</id>
<published>2018-06-20T08:27:32.000Z</published>
<updated>2018-06-20T08:27:32.000Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
<summary type="html">
<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.
</summary>
</entry>
<entry>
<title>作家王小波</title>
<link href="https://blog.yanng.io/2017/09/24/zuo-jia-wang-xiao-bo/"/>
<id>https://blog.yanng.io/2017/09/24/zuo-jia-wang-xiao-bo/</id>
<published>2017-09-24T07:24:54.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>一直挺想写王小波,想让更多的人知道他写的东西,可惜无论怎么写我觉得都是惨淡的。有人说他是世纪末唯一一个活明白的人,可惜就是走的太早,不过可贵的是他写的东西还能留到至今。见得一书评,由 @nici 所写,冒昧搬过来,一同了解王小波。</p><p>20年前的今天,也就是1997年4月11日,王小波病逝于北京。今天写个关于他的书评,也算是个巧合吧。</p><p>曾经大学里会流行这么一句话:男生不可不读王小波,女生不可不读周国平。高晓松曾这样评价说:以我有限的阅读量,王小波在我读过的白话文作家中绝对排第一,并且甩开第二名非常远,他在我心里是神一样的存在。</p><p>据说,王小波一度成了一个接头暗号,文青们根据对王小波的喜爱程度辨别对方是否为同类,可是,无奈我可能有些许“反骨”,越是大众趋之若鹜的,越是打心眼里抵触;越是眼见着大家如火如荼地在王小波死后掀起了这场轰轰烈烈的造神运动帷幕,越是想在内心冷静之后再一个人关起门来阅读被符号化了的王小波的书。于是,在读了他的几本书之后,在读完放置了n久之后,有了下面的内容。</p><p>其实,对王小波作品的风格趣旨进行解读,看看王小波哪里受了福柯影响、哪里体现了虚无主义,自有专家学者和大批迷弟迷妹们去做,还轮不到我来献丑,我喜欢王小波理由一点也不深刻和复杂,就跟我欣赏其他男人的标准一样,第一,独立思考。第二,智慧担当。第三,幽默风趣。</p><p>第一,独立思考,用自己的判断力来寻找真理。尼采曾在一首诗中说“有一天有许多话要说的人,常默然把许多话藏于内心。有一天要点燃闪电火花的人,必须长时间做天上的云。”王小波就像天上的云一般,追求自由自在–精神自由、心灵自由和人性自由。王小波曾说“你知道我在世界上最珍视的东西吗?那就是我自己的性格,也就是我自己思想的自由”,连李银河都认为“在我心目中,小波是一位浪漫骑士,一位行吟诗人,一位自由思想家”。</p><p>与其说王小波是向往自由,不如说他是愿意独立思考。越是读书,我越是发现思辨力是一项多么重要且不可多得的能力。当大多数人都选择沉默的时候,当大多数人都安分守己、甘于平庸,不敢不愿不想思考,以至于或主动或被动地选择或陷于“平庸之恶”时,他却敢于大胆表达、乐于当个“另类”,而且,不是为了另类而另类,不是为了叛逆而叛逆,只是因为“我活在世上,无非想要明白一些道理”而选择思考。对于一切有独立思考能力的人,一直以来我都很喜欢。</p><p>第二,智慧担当。王小波对我的吸引力不仅限于有独立的思考力、不人云亦云,更在于他对自由的追逐、对人生理想的坚持不必以牺牲或殉道这种惨烈的方式来呈现,不必像顾准、老舍、潘光旦、陈寅恪甚至梁济、王国维那么悲剧和令人唏嘘的结局,而这种“有别于常”的方式正是王小波的“智慧”。</p><p>诚然,这里有因时代因素所造就了的王小波走了一条简单的“有别于常”的非悲剧的道路的机会,年轻气盛时我会不以为然,甚至深感丢脸。但是,我想说,当我们的人生有了一定的阅历之后就会发现,把人生之路越走越宽何尝不是一种性格、一种智慧、一种担当。智慧是什么?智慧是选择,智慧也是隐忍,智慧更是藏珠韫椟。宁为玉碎不为瓦全地保有尊严和理想的“贞洁行为”不是不好,但在了解了季羡林、汪曾祺、杨绛等人的牛棚、干校经历之后,我越发觉得在艰难境遇里选择韬光养晦、厚积薄发其实并不简单。智慧的人,我喜欢。</p><p>第三,幽默风趣。林语堂曾说“幽默没有旁的,只是智慧之刀的一晃”。确实,智慧不足的人没有幽默,而只有滑稽;智慧刚好够用而没有富余的人也没有幽默,而只有一本正经;只有智慧足够而有盈余的人,才有幽默,因为幽默是智慧的自然流淌。而王小波最为人称道的可能正是他够大胆、够荒诞的黑色幽默,看到那些或是恶毒腹黑大实话、或是清新淡爽的小鸡汤、或是堪比韩剧桥段的肉麻缠绵情话,你完全可以想见这家伙放到今天绝对是个“一句能顶一万句”的金句段子手,绝对完胜那些自吹自擂号称大V的自媒体,甩那些东拼西凑矫揉造作的公众号n个光年,然后你就可以想见王小波那张丑脸上又会泛起坏笑,然后你就知道什么叫玩世不恭、什么叫狡黠闷骚。哈哈,这种时而温柔似水、时而撒娇耍赖、一贯聪明绝顶、一贯机智幽默、一贯学识渊博的理工男(据说,王小波会编程,1997年,王小波正是猝死在了用于写作的电脑前),我喜欢。</p>]]></content>
<summary type="html">
<p>一直挺想写王小波,想让更多的人知道他写的东西,可惜无论怎么写我觉得都是惨淡的。有人说他是世纪末唯一一个活明白的人,可惜就是走的太早,不过可贵的是他写的东西还能留到至今。见得一书评,由 @nici 所写,冒昧搬过来,一同了解王小波。</p>
<p>20年前的今天,也就是199
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
</entry>
<entry>
<title>人生如戏,演员何苦为难演员</title>
<link href="https://blog.yanng.io/2017/09/24/ren-sheng-ru-xi-yan-yuan-he-ku-wei-nan-yan-yuan/"/>
<id>https://blog.yanng.io/2017/09/24/ren-sheng-ru-xi-yan-yuan-he-ku-wei-nan-yan-yuan/</id>
<published>2017-09-24T07:21:28.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>最近刷完一本名字特别鸡汤的书,叫《所谓情商高,就是会说话》。</p><p>这本书的作者是来自日本的一名广告鬼才、文案写作大师佐佐木圭一,因写过一本《别把成功卡在说话上》而闻名。</p><p>窃以为人的潜意识里觉得缺少什么,那日常必定会强调什么。我想这也可能就是社交软件之所以会有类似朋友圈这种分享功能的原因。</p><p>从没想过我会选择为了提升情商而去专门找一本方法论去攻读。总认为如果把它当作指标刻意去针对地研究,本身就是一种低情商的行为。</p><p>想起曾经有一次我问到朋友:「哎你说,我的情商可不可以用智商去弥补?」</p><p>结果朋友甩来一句:「说的好像你也有智商一样」</p><p>我……</p><p>然而,我还是刷完了这本书。</p><p>我承认其中的方法论还是有一些用处的,第一章结尾就有所总结:</p><blockquote><p>①利用“投其所好” 既能获得对方的好感,又能实现自己的期望。 ②利用“儆其所恶” 能形成强大的强制力。这是措辞的最终手段。 ③利用“选择的自由” 能够引导对方,同时又不会留下被迫感。 ④利用“被认可欲” 对方即使很难对付,也会乐于回应期待。 ⑤利用“非你不可” 能让对方感到只有自己被选中的优越感,从而乐于做出回应。 ⑥利用“团队化” 能使对方产生伙伴意识,即使是麻烦的请求,也会乐于接受。 ⑦利用“感谢” 能让对方隐约产生信赖意识,从而难以轻易拒绝。</p></blockquote><p>看完第一章,我稍稍地阴谋论了一下已经可以灵活运用书中所写到方法的人。有些细思极恐,他可以从脑中像从背包里挑选装备一样轻松地使用说话的技巧,从而达到自己的某种目的。</p><p>啧,很可怕了。</p><p>这就好比有人研究出一劳永逸的解决方案,只要照做,就一定能变成想要的样子。如果掌握了技巧,那岂不是可以任意穿梭时空?按照正确的方法,人类一定可以长生不老……</p><p>吓得我赶紧收回戏精一样的思维。</p><p>书的后半部分倒是让我觉得写的有些乱,好像慢慢就跑到营销相关的消费者心理学方面上了。比如一句文案,套用以上的哪种方式,便可以将商品的收益得到提升。描述的形式又类似于综艺节目问答环节,让人一头雾水。甚至完全抹掉了书的前半部分给我的好感。所以在这里也就不展开讲了。</p><p>不过话说回来,全书最有用的一句话就是:<strong>所谓合不来,其实原因多在于没考虑过对方的心理。交流的基本就在于「能在多大程度上揣摩对方的心理」。</strong></p><p>我觉得这才是人与人之间交流的精髓所在,无论是“投其所好”还是“儆其所恶”之类情况,了解对方的需求比什么都重要。掌握了对方的需求,那么在一定程度上,自己的需求也就被满足了。</p><p>总之,人生如戏,该配合你演出的我尽力在表演。</p><p>另说一句,爸爸以后再也不买鸡汤书了。[再见]</p>]]></content>
<summary type="html">
<p>最近刷完一本名字特别鸡汤的书,叫《所谓情商高,就是会说话》。</p>
<p>这本书的作者是来自日本的一名广告鬼才、文案写作大师佐佐木圭一,因写过一本《别把成功卡在说话上》而闻名。</p>
<p>窃以为人的潜意识里觉得缺少什么,那日常必定会强调什么。我想这也可能就是社交软件之
</summary>
<category term="书评" scheme="https://blog.yanng.io/categories/%E4%B9%A6%E8%AF%84/"/>
</entry>
<entry>
<title>前端?</title>
<link href="https://blog.yanng.io/2017/03/29/qian-duan-2/"/>
<id>https://blog.yanng.io/2017/03/29/qian-duan-2/</id>
<published>2017-03-29T09:18:50.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>这几天刷知乎,想更多的了解前端这个职业。呵。果不其然,都在说当今最火的职业非前端开发莫属。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/timg-2.jpeg" alt=""></p><p>前端工程师:</p><p>一半是designer(设计师)</p><p>一半是coder(程序员)</p><h2 id="我看前端"><a href="#我看前端" class="headerlink" title="我看前端"></a>我看前端</h2><p>前端有多火?</p><p>前端工程师这个职位在智联招聘排行榜蝉联了三个月的榜首,每天都有大量的市场需求,就连十八线城市都缺前端人才。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-03-05-%E4%B8%8B%E5%8D%886.02.31.png" alt=""></p><p>(智联排行榜)</p><p>根据中国人啥火就一窝蜂往里扎蹲儿的尿性,相比前两年最火的UI设计师,前端无疑是很多即将毕业的学生的选择。</p><p>市场需求变化这么快,根本就不给一些毕业生反应的机会。而培训机构往往会比毕业生走的靠前。</p><p>很多人疑惑,为啥花了将近两万的学费培训了大半年出来找工作还是这么难?</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG152.jpeg" alt=""></p><p>(前几日刷屏的有关UI设计师的梗)</p><p>先卖个关子。现在有个特别有意思的现象,大公司总是缺高级前端工程师,而社会上那些培训班速成出来的web开发相关的大量的人却找不到工作。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG153.jpeg" alt=""></p><p>(前端工程师相亲的梗)</p><p>不止前端,还有UI设计师,会计师,微信公众运营,挖掘机,烹饪厨师等等,类似这个现状的例子不胜枚举。</p><p>互联网市场瞬息万变,职位也是不断地在变化,尤其是在中国——世界第二大互联网大国。大部分的职业供求其实呈一个橄榄球状,顶端人才和初级人士位于两端,中规中矩的人才一抓一大把,这也是为什么那些除了初学者或是精英的人会经常感觉到竞争如此之激烈的原因。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/d96bcca74b4d4a010c3b17366685cc18_r.png" alt=""></p><p>(前端工程师必备技能)</p><p>培训机构虽然能走到毕业生前面,却始终追赶不上市场的变化。后知后觉的学生花了大把的学费才发现该职业的火热期早就过去了,悔不当初却也没有任何补救的措施。</p><h2 id="理想主义"><a href="#理想主义" class="headerlink" title="理想主义"></a>理想主义</h2><p>当年高考前,为了激励自己学习,经常狂补鸡汤,找《乔布斯传》等之类的大佬自传看,之后便痴迷于互联网大佬们的创业故事。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG154.jpeg" alt=""></p><p>(左一是《成为乔布斯》作者布伦特·施兰德,左二是比尔·盖茨,左三是史蒂夫·乔布斯)</p><p>虽然现在知道,当时只是不同国情下的时势造英雄的特例,但目前仍如崇尚美国个人英雄主义情结一样,具备理想主义色彩般的人格,并挥之不去。</p><p>用人话说就是,对待事儿总爱抱有一定的幻想,思考问题不从现实的眼光出发。</p><p>就像看漫威长大的孩子,总以为自己有天能够拯救世界。看大佬创业的故事,就会天真的以为自己拥有改变世界的力量。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-03-05-%E4%B8%8B%E5%8D%887.25.07.png" alt=""></p><h2 id="入不入坑?"><a href="#入不入坑?" class="headerlink" title="入不入坑?"></a>入不入坑?</h2><p>高考完等成绩公布的日子挺难熬,选专业更头疼,还好可以刷贴吧论坛消磨时间。</p><p>当时年轻不懂套路,被培训机构软文深深打动,看搬砖屌丝如何逆袭成为IT老鸟走向人生巅峰,看的我热血沸腾。</p><p>心想咱也挺喜欢瞎折腾。那会儿就在某宝上买零件自己组装过一台iPhone4,在PC上装黑苹果倒腾各种驱动,刷机root安卓手机,瞎几把用Ae做特效,PS作图和Pr剪辑片子玩儿……</p><p>虽说是初生牛犊子水平,但对技术的痴迷已经无法自拔。就像无所不能的父辈,接电线换车胎修空调,什么都难不倒生于70年代的他们,工业的骨髓已经随着信息时代的步伐渐渐渗入到我们的血液里。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/203314.jpg" alt=""></p><p>(工匠的形象)</p><p>填专业时考虑到诸多因素,权衡利弊之下做出了选择:省内的学校一律学传统行业的专业,如机械土木等。省外的学校一律学计算机,如软件网络之类。</p><p>嗯,最终被「机械设计制造及其自动化」录取。</p><p>还没反应过来,就已经大三了。三年时间其实一直过的心不在焉,那感觉就像在和一个不喜欢的人谈恋爱。</p><p>考虑过学习的语言和方向。Java、C语言,自学了一段时间,如今只会写个hello world。看过很多iOS开发,Android开发的书,发现不会一门语言真的是举步维艰。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/20150306100933317.png" alt=""></p><p>(所有的编程语言)</p><p>我觉得最恶心的就是一直犹豫不决。不止一次地想要说服自己,编程这个饭碗不要轻易端起来,“吃青春饭”,“话少钱多死得早”这些并不是危言耸听,安心找个朝九晚五的工作安稳地过日子吧……</p><h2 id="博客之路"><a href="#博客之路" class="headerlink" title="博客之路"></a>博客之路</h2><p>两年前一次偶然的机会,我接触了阿里云服务器,慢慢学会了买域名,WordPress建博客,套用大神做的主题,也算是像模像样地会做网站了。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-03-05-%E4%B8%8B%E5%8D%886.56.26.png" alt=""></p><p>(我的个人博客)</p><p>最早知道的个人博客,要属@罗磊的博客,一路下来,看着他和@杨左到处旅行,直到两个人拿到结婚证。从他的博客中学到不少东西,一直佩服磊哥的执行力和分享精神。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-03-05-%E4%B8%8B%E5%8D%886.28.32.png" alt="">(<a href="https://luolei.org)" target="_blank" rel="noopener">https://luolei.org)</a></p><p>我建立博客以来,接触到了不少前端的东西,也写了很多文章,始终庆幸自己没有丢掉深度思考的能力。</p><h2 id="一次事故"><a href="#一次事故" class="headerlink" title="一次事故"></a>一次事故</h2><p>期末是高校查分的高峰期,集中几天访问量居高不下,大部分查分网站都挂了。</p><p>微信后台接的第三方查分网站是超级xx(不便透漏),这些年一直在用。它有简洁美观的UI界面,而且因为是类似爬虫的原理,直接可以把各大教务系统的学生成绩和课表等数据直接抓包读取,安全系数较高。同时这样还跳过了学校要求的评价教师的机制,这也是大部分学生爱用它查成绩的主要原因。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/666.png" alt=""></p><p>(微信查成绩UI界面)</p><p>但这次查分高潮也没能让它幸免于难,整个二级域名直接不能访问。原因不用想也知道,服务器带宽太小,访问人数过多直接崩溃了,这就导致接入的200+的高校都不能使用查成绩功能。</p><p>着急了好几天。联系后台开发人员,但是听说他们当时接了一个项目,在没日没夜赶工程,顾不上修复,也没时间理我。</p><p>好的一点是官网把成绩课表的代码开源了,可以自己建服务器搭载教务系统。但代码是Java写的,我用了一个礼拜的时间,始终不会把代码挂载到服务器上,数据库文件也不知道怎么调试。</p><p>几乎每天都有很多人在微信后台留言,问为什么总是查不了成绩。那次,我深刻的知道了什么叫做绝望,以及掌握一门技术是多么的重要。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/1370655453426.jpg" alt=""></p><h2 id="二级试水"><a href="#二级试水" class="headerlink" title="二级试水"></a>二级试水</h2><p>因为要考计算机二级,接触了web程序设计的一些东西。用了一个礼拜时间过了一遍HTML和CSS的基础,又看了看知乎上一些前端的行业分析,觉得自学起来问题不大。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/timg%E7%9A%84%E5%89%AF%E6%9C%AC.jpeg" alt=""></p><p>其实计算机二级证书对于以后的职业生涯没有任何用处,但还是觉得要有个起点来打开前端的大门。或许我会感激当时报名时临时将二级C语言改成二级web程序设计的决定吧。</p><h2 id="焦虑"><a href="#焦虑" class="headerlink" title="焦虑"></a>焦虑</h2><p>或许对未来太过于敏感,而又想保留有一点点的理想主义。经历了几年不断地试错,大致规划与重新规划,矫正方向使得逐渐妥协于现实,让理想变成幻想还是落地,总想保有顾全大局的幼稚想法却总会失去更多。</p><p>我觉得这才是我最真实的境况。想法一团乱麻,写的东西也是逻辑混乱。看似说了好久,也说了好多,却又好像什么都没有表达,也不用表达的特别清楚。反正是写给自己看。</p><p>慢慢的。关掉了空间,删掉了微博,不去看朋友圈,变得不会表达,荒废了微信公众号。每过一阵把自己的思绪理一理。</p><p>想到过去,想到将来。</p><p>焦虑,皆由心生。</p>]]></content>
<summary type="html">
<p>这几天刷知乎,想更多的了解前端这个职业。呵。果不其然,都在说当今最火的职业非前端开发莫属。</p>
<p><img src="http://xiaobs.cc/wp-content/uploads/2017/03/timg-2.jpeg" alt=""></p>
<p>前端
</summary>
<category term="前端" scheme="https://blog.yanng.io/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="文章" scheme="https://blog.yanng.io/tags/%E6%96%87%E7%AB%A0/"/>
<category term="前端" scheme="https://blog.yanng.io/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>随笔</title>
<link href="https://blog.yanng.io/2017/03/14/sui-bi/"/>
<id>https://blog.yanng.io/2017/03/14/sui-bi/</id>
<published>2017-03-14T13:24:40.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>小时候会羡慕那些认识好多人的同学,下了课上个厕所一路都有可以打招呼的人。</p><p>不管关系熟不熟,但总不会出现一个人走时的那种尴尬。</p><p>现在明显不同于以往的境况,在路上走时会时不时的撞见认识的人,有的只有一面之缘。相视一笑,擦肩而过。</p><p>也算是得到了曾经想要得到的东西吧。但已不同那时的向往,一直想和一些无效的社交断他个干净。</p><p>之前,可能会焦虑于写不出东西。每次装得一本正经,仪式感凝重,又恐于胡说八道之嫌,且又不想陈词滥调。</p><p>如此一来二去,自己就把自己束缚,但又总觉得想表达点儿什么。</p><p>现在,反倒释然了。既然没有想说的,那就不要说了。记录只是一种生活方式,但更重要的是能活得舒坦一点。人生不就这点儿可怜的追求么。</p><p>高强度的写作很累,索性甭写了,打两把游戏,跟朋友吹吹牛逼,何尝不也是过日子。</p><p>貌似现在去真存伪才是这个社会的潜规则。</p><p>就当我是个悲观主义者吧,总是只能看到阴暗的那一面,正能量都是那些演员的即兴表演。至少感同身受过的是这个样子。</p><p>尤其在这片厚德载物的土地。既然德可以载万物,为什么还是放不下那扯淡的面子,只听得进违心的谗言,容不下真诚的怼呢?</p><p>看来,船大能度人,心小却放不下一粒沙。</p><p>前两天吃完晚饭和舍友侃大山,说起这个萨德系统。从抗韩扯到第三次世界大战,从乐天扯到经济贸易全球化。把年轻人的脑洞惊奇口无遮拦发挥的淋漓尽致。</p><p>随着话题的深入,一些信息量略少的,或是有其他事儿的参与者便纷纷退出扯淡的阵营。剩下的二三人学着战略忽悠局局座的模样儿继续满嘴开炮。</p><p>每次总是无一例外地回到那个困扰所有人的三大终极问题——我是谁,我从哪儿来,我要到哪儿去。</p><p>得。自己的事儿还没整明白,就甭咸吃萝卜淡操心了,该干啥干啥去。</p><p>群众生活环境安逸,戾气却是不小。</p><p>虽文化水平良莠不齐,但都学会了如何娴熟地使用阴谋论。整日付精力于妯娌邻里同事之间,抠细节在柴米油盐里。</p><p>不可否认,这也是一种生活态度。</p><p>想起了老罗的锤子手机针对跑分软件负优化的事儿。</p><p>所有厂商的手机都在堆砌发烧硬件,再在系统层面调教,好让手机能在安兔兔上跑出高分。锤子却反其道而行之,检测到跑分行为主动降频CPU使分数低的用户想骂娘。</p><p>只是举个例子想说明目前的写作也是这样。文章无论从何种角度都不具备爆文的气质,这又何尝不是一件好事情。</p><p>行了,想到哪儿写到哪儿。</p>]]></content>
<summary type="html">
<p>小时候会羡慕那些认识好多人的同学,下了课上个厕所一路都有可以打招呼的人。</p>
<p>不管关系熟不熟,但总不会出现一个人走时的那种尴尬。</p>
<p>现在明显不同于以往的境况,在路上走时会时不时的撞见认识的人,有的只有一面之缘。相视一笑,擦肩而过。</p>
<p>也算是
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="碎碎念" scheme="https://blog.yanng.io/tags/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
</entry>
<entry>
<title>没题目</title>
<link href="https://blog.yanng.io/2017/03/01/mei-ti-mu/"/>
<id>https://blog.yanng.io/2017/03/01/mei-ti-mu/</id>
<published>2017-03-01T08:51:43.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>从家走的时候收拾东西,无意中在抽屉里翻出了几张褶皱不堪的信纸。 情书? 不能啊,谁给谁的? 打开发现是三年前自己给自己写的一封信。 当时写完就把信让爸看去了,之后信的去向就不得而知。 现在居然还能重见天日,多亏自己当初没夹课本儿里,不然早被扔锅炉里烧了。 走的时候把信偷偷揣进兜儿,等车还没来,抱着新鲜感翻出来瞅了一遍,虽然这是自己写的。 <img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG145-2-150x150.jpeg" alt=""> <img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG146-150x150.jpeg" alt=""> <img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG147-225x300.jpeg" alt=""> <img src="http://xiaobs.cc/wp-content/uploads/2017/03/WechatIMG148-225x300.jpeg" alt=""> 嗯,字儿还说得过去。(2333) 看的过程中我不停寻思,其实最想知道的就是当时写信的我混的咋样,而如今的我又是个什么逼样儿。 三年,其实不长,却也不短。 那时,我还是一个唯唯诺诺,遇事举棋不定的少年,走路低头看地极度不自信,整天忧郁不知何去何从。 唉,真他娘的没出息。 现在,改变了哪些,又在哪里做出了些许妥协。 三年或是个分水岭。而一封信就像是之前的记忆抽出来的片段,把我拉到历史里的我面前,如同在镜子里窥视全身赤裸的自己。 曾经眼神里经常闪烁的东西如今是否变得浑浊,坚守的价值观有没有被颠覆,一直秉承的理想主义又消磨殆尽多少。 答不上来,只知道变了。 变得越来越现实,越来越市侩,变得更熟练的察言观色,学会了油嘴滑舌的腔调,浑身上下的套路,各种段子也信手拈来,懂得了遇事总会作出一定的妥协。 有人托着下巴说这是生存之道,有人攥着拳头说这活得不地道。 听过太多的「过来人」说:世间无趣的正人君子太多,缺的是训练有素的流氓。 为什么会变成这样?恐怕都在反思的同时,渐渐磨平了本就有的棱角…… 妈的,又扯远了。 该进站了。还记得走之前在家吃的最后一顿饭,是爸连夜准备的炸酱面。刚取到票后接的电话,是妈殷切的问候。 复杂的心情和茫然的感觉有种说不出的滋味,在站台蜉蝣一般地立着。 信里又好像什么都没有写,我也好像什么都没有说。 朝着和谐号开来的方向,看着远处的小黑点慢慢变大,混沌的目光似乎在等待着某个东西的洗礼。 那是什么? 我不知道。</p>]]></content>
<summary type="html">
<p>从家走的时候收拾东西,无意中在抽屉里翻出了几张褶皱不堪的信纸。 情书? 不能啊,谁给谁的? 打开发现是三年前自己给自己写的一封信。 当时写完就把信让爸看去了,之后信的去向就不得而知。 现在居然还能重见天日,多亏自己当初没夹课本儿里,不然早被扔锅炉里烧了。 走的时候把信偷偷揣
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="碎碎念" scheme="https://blog.yanng.io/tags/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
</entry>
<entry>
<title>万物皆有裂缝,那是光照进来的地方</title>
<link href="https://blog.yanng.io/2017/02/17/luojisiwei/"/>
<id>https://blog.yanng.io/2017/02/17/luojisiwei/</id>
<published>2017-02-17T09:35:55.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>万物皆有裂缝,那是光照进来的地方。</p><p>这是我最近看到最多的话。自从莱昂纳德·科恩离开这个世界,他的这句歌词变成了各个行业最爱用的一句话。</p><p>元旦的时候和几个朋友通宵打麻将,也就没顾上看 <strong>《时间的朋友 2016 》</strong> 跨年演讲,之后也没找出视频,而是直接看书,边看边标记反而更能捕捉到一些值得收藏的地方。</p><p>不算太长的 38600 字演讲稿,我年前年后零碎的时间加起来用了三个小时才读完。过程较仔细,因为每一节都能引发很多思考,干脆慢下来,甚至想再慢一点。</p><p>对于这篇演讲稿,倒剖析不出什么商界的秘密,咱也没有那能力。所谓“外行人看热闹,内行人看门道”,更多的是看看罗胖对这一年互联网热度事件的解读方式。</p><p>黑天鹅</p><p>演讲以黑天鹅事件为切入点。</p><p>2016 年确实有三大难忘的黑天鹅事件:</p><ul><li>3 月 15 日的 AlphaGo 围棋打败李世石;</li><li>6 月 24 日英国脱欧;</li><li>11 月 9 日特朗普获总统大选。</li></ul><p><strong>什么是黑天鹅?</strong></p><p>黑天鹅代表不确定性。在发现澳大利亚的黑天鹅之前,17世纪之前的欧洲人认为天鹅都是白色的。但随着第一只黑天鹅的出现,这个不可动摇的信念崩溃了。黑天鹅的存在寓意着不可预测的重大稀有事件,它在意料之外,却又改变着一切。</p><p>演讲中一共提到了 <strong>五只黑天鹅</strong>。</p><p>第一只黑天鹅:时间</p><p>2016 年资本界,或着说是互联网圈存在的现状。移动互联网份额依旧在疯涨,至少每人一部手机,而且是智能手机;BAT 日收入依旧以亿为单位计算,互联网市场还是百度、阿里、腾讯三巨头占据上风……</p><p>2016 年的流量之战,虽然不断有年轻的公司试图进来瓜分流量,但无可否认 BAT 总是赢家。因此行业内有了那句:</p><p>“过去几年,市场上出现了这样的江湖门派,不是姓马,就是姓马。”</p><p>在这里多提一句,为什么不姓李?跟百度 200 亿投资糯米做百度外卖有关,为了拓宽市场,李先生不惜重金,同时也精疲力尽。再加上这一年各种公关危机事件,导致现在百度的市场份额远远不及腾讯阿里,这么做值不值?时间会证明一切。</p><p>我们再回到主题上,时间。罗胖在演讲上提出了一个概念,<strong>GDT</strong>(即Gross Domestic Time,国民总时间)。未来时间才是商业的终极战场,谁能让用户支付时间,谁就是赢家。</p><p>如今我们的日子越过越好。我想起了郭德纲在一档综艺节目回应观众的话。我们很早以前用的杯子,没现在花样儿多,有玻璃的、不锈钢的、瓷的、高脚的等等,在那个时候的人看来,现在家里放着么多种杯子就是吃饱了撑的,但你现在一点儿也不觉的奇怪。这是因为 <strong>时代好了,消费也升级了。</strong></p><p>消费升级,在我们的身边正在展开,有的时候你看到的东西是一模一样,但是它背后的那个道理正在发生变化。这也就不难理解吴伯凡说的那句</p><p>用户不会再为柴米油盐酱醋茶的“茶”而付钱,用户会为琴棋书画诗酒茶的“茶”而付钱。</p><p>第二只黑天鹅:服务</p><p>如何在时间的战场上取胜呢?</p><p>除了上面提到的让用户支付时间,还要为用户着想,优化用户的时间。</p><p>如果你能为用户整个消费的效率最大化,无疑就取得了用户最大的满意度,甚至可以培养用户形成成瘾现象。</p><p>不确定的失去,让人恐惧。不确定的得到,让人兴奋。</p><p>赌场、餐厅和游戏都用到了成瘾设计。</p><p>第三只黑天鹅:智能</p><p>这里的智能指的是人工智能。</p><p>提到人工智能,最火的大概就是 AlphaGo 了。2016 年,谷歌、苹果、亚马逊、Facebook、微软以及国内的 BAT 等,都在人工智能领域有所动作。</p><p>说起人工智能,就少不了前些年特别火的词——大数据。其实在校园,经常可以见到「大数据培训」的机构到处发传单,我接过一张传单扫了一眼,对朋友说,这东西前景还不错,但 <strong>只有大企业才有能力收集大数据,也只有大企业才能把手头的大数据的价值发挥出来。</strong></p><p>人工智能的未来谁都看不清楚,但做它总没有坏处。</p><p>第四只黑天鹅:认知</p><p>2016 ,我们的认知在不断变化。</p><p>感受最深的就是:多家直播平台拔地而起,催生了大批网红。</p><p>徐小平这么定义网红——<strong>不靠任何传统权威认证,自己就能拥有权威的权威。</strong></p><p>艾克里里、天才小熊猫、回忆专用小马甲、谷阿莫、追风少年刘全有、old先、小野妹子学吐槽、英国报姐、同道大叔、一只鸡腿子、黄文煜小盆友、使徒子、谷大白话、咪蒙、胡辛束、越心Nami、哆啦baby、佟丽娇、雨薇薇、_kimmyyyybaby、冉大人、安然、miya、林言-高服帅、sunlike、PDD(娇妹)、miss、小智、white、若风、55开、uzi、小漠、骚男、笑笑、董小飒、张大奕、雪梨、onlyanna、林珊珊、喜哥、delicious大金……</p><p>我承认我只知道其中的几个,我敢说你也不可能全都认识。</p><p>不管你听没听过,不管你同不同意,不管你喜不喜欢,他们都红了。我们这个时代神奇就神奇在这儿。</p><p>还有个例子。我们每天的生活都是碎片化的,而「快手」就很好的抓住了这一点。目前它估值 206 亿,日活跃用户 4000 万,就在写这篇文章之前的不久,有传言称快手将于下半年赴美上市。</p><p>这也就不难看出微博、QQ空间和今日头条为什么极力想做短视频这块儿。每次朋友打发时间刷微博小视频,我都会调侃:“又看快手呐”。</p><p>不得不说, 2016 是颠覆认知的一年。而我们,也都 <strong>被迭代</strong> 着认知。</p><p>第五只黑天鹅:共同体</p><p>在正式开始之前,罗胖又引入一个“后真相”的新概念。</p><p>后真相的意思,不是没有真相,而是对这个世界来说,情绪的影响力已经超过了事实。</p><p>如今人们建立共同体的方式发生了变化。除了国家,血缘、地域、阶层、单位、专业,以及认知,这些体系的概念在逐渐模糊,甚至脆弱。</p><p>曾经在朋友圈看到过几句话,印象较为深刻。</p><p>网络社交很脆弱。平时你我有千万个共鸣,但今天只要有一件事看法相反,可能彼此就认为对方是傻屌了。总之,现在表达个人喜好是件瞻前顾后的事。</p><p>自打人类出现,抱团取暖便成了人的本能。但随着越来越浮躁和充斥各种欲望的社会发展,人类对共同体的认知变得不是那么清晰。<strong>市井喜欢看热闹,看客愿意追八卦,强者希望对手倒下……</strong></p><p>他们不肯多一点点肯定和喝彩,但绝不少一点点质疑和批评。</p><p>我们不必非要将自己和当事人绑在一起,但至少做到不黑。</p><p>领悟</p><p>所谓更牛,就是换个罪受。</p><p>这是 2016 年让罗振宇领悟最深的一句话。</p><p>作为观望者,我完全同意这句话。一切努力和苦逼,都是为了更牛,为了更加体面,为了实现更大的价值。其实我的领悟:</p><p>要想成为一个体面的人,你得是个理想主义者。但前提,你更得是个执行者。</p><p>以上。</p><p>题图来自:CC0</p>]]></content>
<summary type="html">
<p>万物皆有裂缝,那是光照进来的地方。</p>
<p>这是我最近看到最多的话。自从莱昂纳德·科恩离开这个世界,他的这句歌词变成了各个行业最爱用的一句话。</p>
<p>元旦的时候和几个朋友通宵打麻将,也就没顾上看 <strong>《时间的朋友 2016 》</strong> 跨
</summary>
<category term="书评" scheme="https://blog.yanng.io/categories/%E4%B9%A6%E8%AF%84/"/>
<category term="文章" scheme="https://blog.yanng.io/tags/%E6%96%87%E7%AB%A0/"/>
</entry>
<entry>
<title>2016 过去了</title>
<link href="https://blog.yanng.io/2017/01/26/2016summary/"/>
<id>https://blog.yanng.io/2017/01/26/2016summary/</id>
<published>2017-01-25T16:42:30.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>就像有人在朋友圈里说的:</p><blockquote><p>2016,见同样的人,做同样的事,吸同样的霾。</p></blockquote><p>每次过年,每个人像是猝不及防被什么东西扯了一下,不经意就迈过了一道门槛,恍惚间就又老了一岁。如果不是日历变成了 2017,都意识不到自己又过了一年,痴长了一岁。</p><p>一到年底,每个人过电影一样回顾过去的一年,并着手开始那也许<strong>永远完不成的年终总结和 2017 计划</strong>。似乎只有这样,才能找到在这个世界的存在感。</p><h2 id="2016"><a href="#2016" class="headerlink" title="2016"></a>2016</h2><p>每到总结的时候其实有蛮多想说的东西。回过头看看一年前的自己傻逼的样子,心里庆幸这一年没有白活,明年再接再厉,<strong>争取把昨天的自己活成傻逼</strong>,这样才能证实自己确实没有原地踏步。</p><blockquote><p>2016 年依旧发生了不少事儿。</p></blockquote><p>直播平台叫得上来的叫不上来的又多了一大堆;王宝强离婚网上闹的沸沸扬扬现在也成了百姓茶余饭后的谈资;微信小程序的到来也不知道能不能取代臃肿的 APP;薛之谦终于火了;AlphaGo 围棋打败人类;小李子终于获得奥斯卡影帝称号;魏则西事件再次将百度的口碑推向风口浪尖;郭曹师徒在微博开骂战反目;罗一笑也离开了这个世界……</p><p>我们永远无法知道下一秒会发生什么。我们可能什么都不知道,但唯一知道,<strong>嗯,我他妈还活着。</strong></p><blockquote><p>2016 年依旧很忙,但还算充实。</p></blockquote><p>回想一下,感觉像是经历过很多很多事,又好像什么也没有发生过。<strong>有时这操蛋的理想就和操蛋的现实一样,都不太靠谱</strong>。</p><p>年初,我哥意味深长地说,男人在外有三宝:<strong>女人、衣服和手表</strong>。女人指女朋友;衣服就是出门要有一身体面的衣服;至于手表,戴总比不戴有范儿。</p><p>于是,一年过去了,只有手腕上多了一块表……</p><h2 id="去过的地儿"><a href="#去过的地儿" class="headerlink" title="去过的地儿"></a>去过的地儿</h2><blockquote><p>2016 年去的地方挺多。</p></blockquote><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6852-300x260.jpg" alt=""></p><p>清明三天假期,我和朋友俩人去了趟天津,其实就是想换个地方透透气儿。本来想低调压压马路,没想到在天津上学的同学知道,最后一天我们一起吃了个饭,在这里感谢亚茹童鞋和常林童鞋。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_2343-300x300.jpg" alt=""></p><p>天津之眼</p><p>暑假在北京的杨杨哥家住了大概一周。因为全家人都挺忙,我就一个人在北京瞎逛。故宫鸟巢水立方得见见啥样儿,完事儿专门冒雨做公交去了趟朝阳区望京,到锤子科技大厦楼下充值信仰。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6853-281x300.jpg" alt=""></p><p>(身后的 Alibaba 大厦挺嚣张啊)</p><p>从北京回家没几天,就开始着手计划去宿舍哥几个家里认认门。先见了在阳泉上班的贝贝哥和朋友,随后直接北上大同,跑一趟云冈石窟和方特也没算白去。剩下的几天队伍逐渐壮大,应县和朔州相应的逛几个地方,就此“北上”之旅算是结束了。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_4917-300x225.jpg" alt=""></p><p>云冈石窟</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_5018-300x225.jpg" alt=""></p><p>方特欢乐世界</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_5056-300x300.jpg" alt=""></p><p>应县木塔</p><p>十月底去无锡参加“大学生物联网大赛”,顺便坐城际高铁在上海待了一晚。最大感受是:气候太适合我!因为从小就怕冷,又不喜欢穿的太厚重,也不是太受的了北方的干燥。一晚的魔都之旅我甚至产生了做一名“张江男”的想法。</p><p>何为张江男?</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6854-300x293.jpg" alt=""></p><p>熬夜准备比赛的代码,用汉庭的电视当显示器,麻麻再也不用担心我眼花。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6012-300x208.jpg" alt="">)<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>回来把整理所有拍摄的素材用 iPhone 上的 GoPro 官方 APP 简单剪了个视频,还挺方便。</p><p>顺便说一句,无锡上海的妹子身材真心不错~</p><h2 id="看过的电影"><a href="#看过的电影" class="headerlink" title="看过的电影"></a>看过的电影</h2><p>依旧没钱,但还是给不少电影贡献了票房,虽然一年不可能看遍所有自己喜欢的片子,但还是蛮满足的,感谢肯陪我看电影的朋友。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6855-280x300.jpg" alt="">)<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><h2 id="读过的书"><a href="#读过的书" class="headerlink" title="读过的书"></a>读过的书</h2><p>2016 年没少买书,也没少看书。粗略的罗列了一下,半年的时间大概看了 22 本书,平均一周一本的速度。真是“买书如山倒,读书如抽丝”!希望以后继续坚持看书的习惯。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6864-96x300.jpg" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/IMG_6865-57x300.jpg" alt=""></p><h2 id="听过的歌"><a href="#听过的歌" class="headerlink" title="听过的歌"></a>听过的歌</h2><p>平时听歌主用「网易云音乐」,听音乐成了每天都会做的事。手机上使用的高频 APP 除了「微信」、「微信读书」和「Safari」,就是它了。</p><p>晒一下云村用大数据分析的关于我的年度报告:</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/WechatIMG117-174x300.jpeg" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/WechatIMG118-174x300.jpeg" alt=""></p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><h2 id="剁手过的数码"><a href="#剁手过的数码" class="headerlink" title="剁手过的数码"></a>剁手过的数码</h2><p>每年都有败家的数码清单,今年入手了两件电子产品。</p><p>前半年买了一部 kindle 7,后来因为 ppi 太低和没有背光而出手闲鱼,同时又从闲鱼购得一部二手的 kindle paperwhite 2 ,一直用到现在,陪我度过了无数个单身的夜晚。(手捧 kindle ,以书为伴…)</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/134425w731h1h4hhdclblf-300x199.jpg" alt=""></p><p>年底入一台银色的 iPad mini 2( WLAN 32G版),分了三期京东白条,7.9 寸便携性很强,主要用来看视频。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/timg-300x200.jpeg" alt="">)<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><h2 id="写过的文章"><a href="#写过的文章" class="headerlink" title="写过的文章"></a>写过的文章</h2><p>写博客两年了,零零散散也写了不少东西,今年是第三年。目前公众号的内容和博客是同步的,大部分还是以书评为主。</p><p>域名:xiaobs.cc</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/WechatIMG119-300x113.jpeg" alt=""></p><p>每个月尽量让自己写点什么,慢慢就积累了不少。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/WechatIMG121-255x300.jpeg" alt="">)<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>网站累计访问量只有 2W , SEO 的优化和网站的热度和访问量有着很大的关系,不过网站每天都有流量,我就很开心了。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-01-25-%E4%B8%8B%E5%8D%8810.42.16-300x106.png" alt="">)<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><h2 id="要说遗憾,谁能没有?"><a href="#要说遗憾,谁能没有?" class="headerlink" title="要说遗憾,谁能没有?"></a>要说遗憾,谁能没有?</h2><ul><li>今年仍然没有开始实施增肥计划,体重 120 斤依然没有变化。</li><li>夜里熬夜,早上赖床的毛病还是没能成功改善。大概是更喜欢独处的时光,白天根本不可能,也只能在夜晚通过透支身体为代价,给自己提供安静的独立思考的时间。</li><li>看的书不够多。</li><li>想买的东西先咽咽口水,只能对自己说再等等吧。没钱要啥自行车?</li><li>还是单身…</li></ul><h2 id="2017-大致规划"><a href="#2017-大致规划" class="headerlink" title="2017 大致规划"></a>2017 大致规划</h2><p>其实我很少定计划,因为计划永远赶不上变化。从马云爸爸的“梦想还是要有的”,到王健林的“先定一个小目标”,所以总要给 2017 年定个大致的计划。</p><p>以前,我总是很贪心。什么事情都想做,什么东西都想要得到。其实要做到所有事情都能兼顾,比登天还要难。希望自己能够弃繁从简,在「想做的事情」方面不断做减法,专心做几件事,并把它们做好。</p><ul><li><p>开始健身计划。增肥增肌,这也是爸妈希望的。</p></li><li><p>接触前端。计算机等级考试选的 web 程序设计,自己也乐此不疲的折腾了几年时间。既接触代码,又涉及交互。通俗地说,相当于前端由一半程序员和一半网页设计师构成,挺符合我的口味。而且前端的前景还不错,随着移动互联网的不断成熟,再加上微信小程序的到来,以后对前端的需求将会越来越大。以后文章再详细说。</p></li><li><p>读更多的书。当务之急,先把 2016 年囤的书看完。</p></li><li><p>写更多的文章。其实每次写作都会有仪式感和强迫症。就像一个段子写的:我在开始写之前,已经下楼买饮料、擦桌子、掀头发、整理桌子、挑歌单很久很久了。希望 2017 能够克服这种病态,让表达不再拘束。</p></li><li><p>经历更多。说的是一些工作经验和社会经验,在成为一个体面的成年人之前,还有很多的路需要走。</p></li><li><p>去更美的地方。如果有机会,仍然愿意去一些美丽的地方看看,和最好的朋友一起。</p></li><li><p>遇见一个人。都说好看的皮囊千篇一律,有趣的灵魂万里挑一。一辈子很长,要跟有趣的人在一起。单身久了,反而觉得书本和机器比人更容易打交道,与其浪费时间寻找,不如把更多的时间用在「做一个有趣的人」更实际。</p></li></ul><p>啰啰嗦嗦写了一大堆,其实写了什么我觉得不是很重要。而是写的过程中,可以想到一些有趣的事儿,期间翻翻以前的相册,可以明白值得交往的人和值得珍惜的感情。也希望有的朋友能从我分享的一年里得到一些东西,这才是主要的。</p><p>其实这长长的一生啊,也不过就八个字:<strong>我自倾怀,君且随意。</strong></p><hr><p>题图来自:Zoommy</p>]]></content>
<summary type="html">
<p>就像有人在朋友圈里说的:</p>
<blockquote>
<p>2016,见同样的人,做同样的事,吸同样的霾。</p>
</blockquote>
<p>每次过年,每个人像是猝不及防被什么东西扯了一下,不经意就迈过了一道门槛,恍惚间就又老了一岁。如果不是日历变成了 201
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="文章" scheme="https://blog.yanng.io/tags/%E6%96%87%E7%AB%A0/"/>
</entry>
<entry>
<title>年轻人就是年轻人,没有所谓牛逼的年轻人</title>
<link href="https://blog.yanng.io/2017/01/25/nian-qing-ren-jiu-shi-nian-qing-ren-mei-you-suo-wei-niu-bi-de-nian-qing-ren/"/>
<id>https://blog.yanng.io/2017/01/25/nian-qing-ren-jiu-shi-nian-qing-ren-mei-you-suo-wei-niu-bi-de-nian-qing-ren/</id>
<published>2017-01-25T12:24:29.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>看 ZEALER 的 2016 年度总结,挺有感触。</p></blockquote><p>王自如在视频里提到的「年轻人」。他说一年的创业时间里,明白了那句“年轻人就是年轻人,没有所谓牛逼的年轻人”其中的深意。</p><p>王自如问 IBM 一高管 (Arita)。</p><p>王:“从业20多年来,有没有见过哪一个年轻人特别厉害?”</p><p>Arita:“没有厉害的年轻人,年轻人就是年轻人。”</p><p>你可能在经历的时间和事情上有一定的压缩和快进,但是在本质上,你飘的越高,你下面空着就越多,早晚是要回来重新补课的。</p><p>无论是人也好,公司也好,其实都是这样,走得太快,一定是回来补课。</p><p>比如说你像跑步、开车,你已经开的很快,你也走得很快,你领先后面对手很远了,在这个时候,你会想慢下来吗?你不会想慢下来了,你会想再快点,再快点,再快点。</p><p>有点类似我们打球,你跑的越快,你越紧张越去思考你每一个动作要领,你反倒觉得你的球投不进去。</p><p>所以今年在这些反思的过程中,深刻领悟到什么叫做没有厉害的年轻人,就只有年轻人。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2017-03-06-%E4%B8%8B%E5%8D%882.53.20.png" alt=""></p><p>看王自如的评测很久了,从他录制各种开箱视频一个人做TechMessager,一直到如今创办壮大的公司ZEALER。</p><p>点点滴滴看着他一路创业到这般规模,除了他有很强的执行力之外,更多的可能是几年前的中国没有一个比较权威的数码产品评测机构,而王恰恰看到了其中的商机。其实按照他的说法,更多的是出于对数码产品的热爱。</p><p>当然现在FView和那岩的科技美学也做的不错,但从团队的规模和工程机到手的优先程度来看,ZEALER可以称得上是国内最大的测评机构。</p><p>不过单单做测评不够,王自如在很早就把公司的方向调整,致力于打造成一个引领个性科技生活的服务商,这些年也确实在这方面下了很大功夫。</p><p>其实有很多人都不太喜欢王自如。有人是因为他拿了雷军的投资,觉得以后的评测会偏颇于小米手机;有人是因为那次王和罗永浩在优酷上直播骂战,他们更愿意选择站在老罗这边;还有人是因为他长得太像他们的爱豆刘翔了….</p><p>不管怎样,王自如和他的团队还是一日既往地坚持下去。</p><p>王自如也在年终总结里提到了团队的反思以及心态调整:</p><p>我们做了这么多事儿,难道是为了那些不喜欢我们的人吗?</p><p>当然不是,我们面对困难面对挑战,然后还依然把这些事坚持下去,然后把这件事扛着走的原因,是为了那些喜欢你的人。</p><p>因为你永远不可能让所有人都喜欢你,但是你要让支持你的人不失望,这个实际上是我们最大的动力,也是我们坚持下去很重要的原因。</p><p>所以对于那些一直坚持和支持我们的人,我也就唯有感谢吧。</p><p>视频:</p>]]></content>
<summary type="html">
<blockquote>
<p>看 ZEALER 的 2016 年度总结,挺有感触。</p>
</blockquote>
<p>王自如在视频里提到的「年轻人」。他说一年的创业时间里,明白了那句“年轻人就是年轻人,没有所谓牛逼的年轻人”其中的深意。</p>
<p>王自如问 IBM
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="碎碎念" scheme="https://blog.yanng.io/tags/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
</entry>
<entry>
<title>春风十里,不如冯唐的随笔</title>
<link href="https://blog.yanng.io/2017/01/20/fengtang/"/>
<id>https://blog.yanng.io/2017/01/20/fengtang/</id>
<published>2017-01-20T08:02:41.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>从正式打开包装到翻完最后一页,大概用了一个月的时间。美学、禅意、世俗、浓情…构成了这本冯唐最美随笔集。</p></blockquote><p>年前要应付学校的期末考,回家后又想如释重负地睡几天。书从学校的书架里,几经辗转到家里的书案上,夹在里面的书签也就挪了不到 5 页。</p><p>现如今大多书的封面都是有个腰封,其实在看书的时候很不方便,每次都是把它拆下来扔到一边,等全书看完之后再装上,才把书收起来。其实也不乏有些好看的腰封,但终究只是皮囊相。买书之前,看的是封面和腰封。买回来之后,封面的各种矫揉造作就和书的内容毫不相干了。</p><p>《在宇宙间不易被风吹散》是冯唐最新的一本随笔集。这本书的封面结构是我见过<strong>最有创意</strong>的,没有之一。</p><p><img src="http://xiaobs.cc/wp-content/uploads/2017/01/2017012014848977675881bde7915b0-300x200.gif" alt=""></p><p>全部打开的样子</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="">)<img src="http://xiaobs.cc/wp-content/uploads/2017/01/wKgJK1ecm1ryG4_BAAO9CLD3XaU656-300x169.jpg" alt=""></p><p>遇到一本好书,往往会让我感到不知所措。即想细细品,又迫切想知道后面的内容。一来二去备受煎熬,无奈只好作罢,每看一会儿便放到一边儿,下次再捧起来。只有这样,才能消除这种矛盾的“病态”,所以很久都没有过一口气看完的书。虽然解释不清到底是什么原因,但这种方式无疑使效率大打折扣,浪费了时间不说,进入状态重启多次有损大脑是亏。看小说还行,好比追剧,吃饭上厕所都不会扰乱思绪。如果是散文,状态不对就好比走马观花,<strong>让你逛窑子,只看花灯不看人,谁亏谁知道。</strong></p><p>讲实话这是我看的第一本冯唐,我挺喜欢他那种雅中带痞的文笔,自恋但不做作的风格。一般看书,我都有随手标注的习惯,喜欢作者写的哪里,总希望能够珍藏下来。初入文学,任何成长的机会都不愿放过。</p><p>看这本随笔期间就收获不少,不妨摘录下来,对自己对他人总有用得到的地方:</p><ul><li>人是需要有点精神的,有点通灵的精神,否则很容易出溜成行尸走肉,任由人性中暗黑的一面驱使自己禽兽一样的肉身,在世间做一些腐朽不堪的事情。</li><li>人是群居的生物,越是在通灵的时候,越希望有知己在旁边起哄架秧子。一杆进洞,四下无人,人生悲惨莫过于此。</li><li>在真正的美面前,文字常常乏力。</li><li>审美的确需要天赋,但是天赋需要点拨,后天熏陶能在相当程度上弥补天赋的不足。多花点时间在这些通灵的事儿,人容易有精神;多用些美器做这些通灵的事儿,人更容易有精神。精神即是物质,物质即是精神,本一不二。</li><li>得之我幸,不得我命。</li><li>借问人生何所有,几床悍妇几墙书。</li><li>周围草木一寸一尺地消失,时间没有方向感,四处流淌。读者和作者一起坐在屌丝时的夏天夜晚来临之前,怎么吃也不隆起的腹肌,怎么流汗也耗不尽的力气,怎么想念也绝不降临的你。</li><li>早在鸡鸡体会肿胀之前,心已经读到肿胀。</li><li>“为了那些细小的需要,从没说要,从不明了,总想忘掉”</li><li>人又不是黄金,怎么能让所有人都喜欢?任何事做到顶尖,都是政治,都会被人妒忌;即使是黄金,也会被某些人说成是臭狗屎。</li><li>二三十年下来,我渐渐形成了习惯,无论四季、地域,接过一杯热热的茉莉花茶,喝一口,沉一晌,气定神闲——准备好了,可以开始消化一切傻逼和混蛋了。</li><li>一生中,除了做自己喜欢的事儿,剩下最重要的就是和相看两不厌的人待在一起。</li><li>在中国,毁一个美景的最简单方式是让人知道这个地方。</li><li>书本永远是起点而已,永远难免苍白无力;一手资料永远、远远大于二手资料。</li><li>身留闲,一年里一定要空出来两三个月的时间,避免应酬,只摄入、不输出,多读、多写,少看或者不看任何评论。</li><li>“欲戴王冠,必承其重。不要低头,王冠会掉。不要哭泣,有人会笑”。这个态度也太励志、太权谋,放松,戴戴耍耍,不留神,王冠掉了,掉就掉了,掉了就索性长发飘飘。</li></ul><p>其实每次说这是「书评」,其实不然。因为并不想对着书评论一二,而只是想抱着谦卑的态度去学习一些东西。随着看过的书慢慢多了起来,越来越觉得自己的渺小与无知,天地万物之无垠。<strong>“每个人都应该有个笃定的核”,</strong>其实就是要做到对外界之事充耳不闻,应当把重心放在对自己身心上的修炼,此为禅。</p><p>万物皆有两面性,一本书也有好有坏。放下给自己强加的主观臆断,接纳书中的一些好的思维方式,感谢冯唐。</p><p>以上,此为得到。</p>]]></content>
<summary type="html">
<blockquote>
<p>从正式打开包装到翻完最后一页,大概用了一个月的时间。美学、禅意、世俗、浓情…构成了这本冯唐最美随笔集。</p>
</blockquote>
<p>年前要应付学校的期末考,回家后又想如释重负地睡几天。书从学校的书架里,几经辗转到家里的书案上,夹在里面
</summary>
<category term="书评" scheme="https://blog.yanng.io/categories/%E4%B9%A6%E8%AF%84/"/>
<category term="书评" scheme="https://blog.yanng.io/tags/%E4%B9%A6%E8%AF%84/"/>
</entry>
<entry>
<title>啪啪啪时你真的什么都不想吗?</title>
<link href="https://blog.yanng.io/2017/01/03/gunchuangdan/"/>
<id>https://blog.yanng.io/2017/01/03/gunchuangdan/</id>
<published>2017-01-03T14:12:35.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<p>在正式开始话题之前,我想讲讲我的性启蒙。</p><p>关于这件事儿,认真追溯起来竟然没有某个特别值得纪念的日子或事情。只是模糊记得一些场景,使得这个世界上的一个普通的孩子经历了神奇般的体验。</p><p>那时的我,不知道 AV 为何物,黄也只是一种看起来感觉暖暖的颜色,对种子这个词的印象也只是停留在《自然》课本里,了解到的日本名字也仅仅与动漫有关……</p><p>其实每个孩子在很小的时候,就学会了大人吹牛逼的样子。而每个男孩在很小的时候,就已经能熟练地模仿父亲跟朋友讲荤段子。虽然有时候并不知道段子里所指的内涵,他们只是觉得这些段子能让他们抱着肚子笑一下午,毕竟童年的时光看起来好像永远都用不完。</p><p>如果非要追究性启蒙到底是什么时候开始的,那可能是因为我偶然间得到的一本书。书的内容现在已经完全记不起来了,不过当时的感觉应该隐约能想起来个大概。</p><p>那是个平常到不能再平常的课间,窗外的蝉嘎吱嘎吱叫的闹腾。一同学神秘兮兮地递给我一本泛黄的书,书已是破烂不堪,看样子已经被人翻看无数次。我看周围没人注意这边,一把接过来就塞进书包,一直到中午放学回家吃完饭,我把房间门插上,躺在床上一页一页忐忑地翻着书。心脏在打鼓,脸烫的如烧红的生铁,下边的玩意儿用王小波在《黄金时代》里开头的描述,那就是:“一生经历的无数次勃起,都不及那一次雄浑有力。”</p><p>大概就是那次,我似乎触动了人类身体上的一个开关,我明白了我从哪儿来,我知道了什么叫作性。</p><p>话说前一阵子刚看完一本书,书名叫《滚床单心理学》。</p><p>虽然里面的案例找的很牵强,但是不影响心理学等方面的科普,很有趣的一本书。</p><p>读的过程中做了一些标注,大多是人类存在的一些有关性行为在心理学上的解释,专业性毋庸置疑。而且涵盖范围也特别广,涉及一些较隐晦甚至敏感的话题都毫不避讳,将各种有关性在心理学上的动机或理论依据等一五一十地阐述,很涨姿势。</p><p>现将标注整理到下面,不想读整本书的朋友可以看一看。</p><hr><p>第<strong>1</strong>章 揭开爱与性的神秘面纱</p><blockquote><p>权力的边际效应有两个层面:一是拥有权力的人周围会有一群可以帮助其脱离困境的人,而这可以降低有权者犯错的成本;二是权力本身会使行使权力的人衍生出“我很优秀”的错觉,误把权力带来的荣誉和尊敬当作自己有能力的标志。</p></blockquote><blockquote><p>有这样一句话:“爱情因性而更加美好,性因爱情而变得神圣。”这句话很好地道出了爱情和性的关系。</p></blockquote><blockquote><p>性有三种目的:繁殖——生育孩子;建立关系——在充满爱和信任的关系里进行性行为;娱乐——得到直接的身体乐趣。</p></blockquote><p>第<strong>3</strong>章 细节探知爱情真意</p><blockquote><p>快节奏的生活让人们来不及思考,来不及认清自己真正的需要,只是被浮在表面的诸多信息和诱惑牵着走,很容易就会迷失在浮躁的社会潮流里,于是便有了“大家都那样,没什么大不了”的心理。</p></blockquote><p>第<strong>4</strong>章 男人为什么会这样?</p><blockquote><p><strong>男性向往乳房的原因**</strong>:** 1,人类初期时男性的恋母情结,而且喜欢更大体积的乳房。 2,人类对异性人体遮盖部位一种求知的渴望。 3,因为自身条件不具备,更加对乳房充满了一种神秘感。</p></blockquote><blockquote><p><strong>导致了女性选择性对象的时候会更挑剔的原因:</strong> 由于女性的生育成本过于高昂(整整十个月的孕期,以及孩子出生后长达十多年的抚育期),使得她们对性对象非常挑剔的。她们除了要看性对象的健康程度外,更要考察对方的物质资源和社会地位,以便挑选出最好、最有保障的合作抚育者。这是个并不容易且需要花费一定时间的过程。</p></blockquote><blockquote><p>双手的解放使人类摆脱了为生存而竞争的被动地位,从而得以“温饱思淫欲”。</p></blockquote><blockquote><p>在动物世界里,所有的雄性动物都在为了生存和交配而埋头战斗。而大自然让它们只在每年的某个固定的时间发情,而其他时间则必须努力施展各种捕猎技术,同时防备和躲避天敌对自己的袭击,这样才能生存下来。而人类的男性只需花费一天中的几个小时就能赚取到足够的生存材料,因此就有大量的未经消耗的能量用于思考、感觉和享受,这给男性的随时发情创造了时间、精力和体力上的基础。</p></blockquote><blockquote><p><strong>男性的性支配能力强于女性的原因:</strong> 在大脑的构造上,男性大脑内与脑垂体相连的下丘脑视前区比女性要大整整1倍,而这个区域的功能是分泌荷尔蒙,以及掌管性想法和性行为。</p></blockquote><blockquote><p>女性的视觉范围比较宽广,可以看到180°范围内的物体,几乎是男性的6倍(男性只能看到30°范围内),这让她们能够快速地看完侧面的帅哥而不被抓住;而男性的视觉范围比较窄,导致他的“看”让人觉得太过于明目张胆。但也许是由于视野范围窄的原因,男性能够看得比较远,所以就比较能解释为什么男性远远地就能看到一个美女正朝他走过来,而女性却对此毫无觉察。 可是这样的不同,并不是因为男性和女性在眼睛的构造上有差异(男女的眼睛构造是一样的),只是因为在进化的过程中,男性多外出捕猎,需要紧紧盯住并跟踪猎物,所以视野就放得远,而不能关注与目标无关的事物,否则就可能一无所获而饿肚子。而女性多负责采摘果实和照顾家庭,这就大大培养了她们“眼观六路、耳听八方”的能力。 所以,在日常生活中,男性最讨厌的就是找东西,因为他们需要上下左右移动自己的头部,并四处查看半天才能找到目标;而女性则只要打开柜子,眼睛一扫就能将所有东西尽收眼底。这就是为什么男人总被逮到正在看漂亮女人,而女人看了很多眼帅哥却依然没被发现的原因。</p></blockquote><blockquote><p>催眠大师艾瑞克森把人分为三种类型:视觉型、触觉型和听觉型,其中视觉型的人是最容易被催眠的。因为他们想象力较丰富,当催眠师用语言、表情、肢体等引导他时,他们比较容易发挥自己的想象力,从而进入被催眠状态。</p></blockquote><blockquote><p>爱情的主要成分是亲密和承诺,即两个人之间有很多的亲密感和很真诚的对彼此未来生活的承诺——亲密建立在彼此了解的基础之上,而要了解彼此,需要一定的时间认真相处才行。</p></blockquote><blockquote><p>和女性比起来,男性大脑里负责情感沟通的区域要小得多,因为当男性胎儿在母体里时,他的大脑曾经大面积地浸泡在睾酮素里面(女性胎儿则不会),这个过程使得他们大脑里面负责情感沟通的区域受到损伤。</p></blockquote><blockquote><p>有些人为了对抗这种自卑的感觉,就会期望选择一个自认为比自己优秀的伴侣,所以就有了今天的年轻人青睐“高富帅”和“白富美”的婚恋现状。</p></blockquote><blockquote><p>婚后容易出轨的男人,他们具有虚荣心强、攀比心重、没有自我独立意识、随波逐流的心理和个性特点。</p></blockquote><blockquote><p>我们的社会已然发展到这个阶段:各种高科技蜂拥而来,网络信息时刻都在爆炸,各种粗制滥造的影视剧充斥荧屏可是人们却乐于接受。在这样的快餐文化之下,每个人都在匆匆的生活,来不及去想自己真正想要的是什么,也来不及核对目前正在行走的是不是自己真正想要走的路,更不会去追问自己内心的感觉是什么,只是看到大家都这样,所以自己也随波逐流。</p></blockquote><blockquote><p>在解剖学上,我们的大脑分为左脑和右脑,而连接左右脑的纽带被称为胼胝体。在进行思维和感知活动时,我们正是通过胼胝体来使左脑和右脑共同协作,以更好地完成各种任务。</p></blockquote><blockquote><p>话语本身原本是中立的,只是文化和道德规范人为地做了区分和定义,从而用来教化大众:遵守规矩就是好的,反之则是坏的。</p></blockquote><blockquote><p>在公共场所,违反道德规范是要受到谴责乃至是惩罚的。可是,在闺房这个私密的空间里,人们自然就想触犯这个禁忌,以获得“违规”的快感。</p></blockquote><blockquote><p><strong>做爱时喜欢开灯的原因:</strong> 他们之所以喜欢开灯,首先是因为男性的性刺激很大一部分来源于视觉,如果能够清晰地看到伴侣的身体、表情、眼神及各种反应等,都能更深地激发、强化男性的欲望和感觉。尤其是当他正和自己心爱的女人滚床单时,看着对方的脸能让他有更强的征服感和满足感。 喜欢在滚床单时开灯的第二个原因,是他们认为床上是坦诚相见的好地方,开着灯自然能将这种坦诚毫无保留地呈现出来。那些对自己的身体很有自信的男人,更加愿意开着灯让女伴欣赏自己身体的美好,尤其是让女伴看到自己的表现有多么的棒。 第三个原因说来就有些打击男性的自信了。因为男人的身体不够敏感,或者说是由于他们更多地用左脑来进行逻辑思考、分析推理,这样就降低了他们身体的敏感度。同时,由于男人对性的目的性更强,很多人只是追求那几秒钟的快感,因而都有些猴急儿地奔着最终目的而去。这样的生理和心理特点,使得他们也懒得慢慢去培养自己的性感受,而是为了达到快速愉悦自己的目的,只好让明亮的灯光来配合刺激自己的神经,从而让自己迅速兴奋起来,并勇往直前地表现自己的雄风。</p></blockquote><blockquote><p>没有了信仰,没有了精神上的追求,人就会感到内心有个巨大的空洞,会有一种整个人飘摇在空中无法仰赖的感觉。此时,人就会随波逐流,并逐渐变得神经麻木。</p></blockquote><blockquote><p>在性的交融中,男人会体验到巨大的快感,而他内心会觉得这快感来自于女人的恩赐,为了对这恩赐表达感谢,他会愿意不遗余力地向那个女人表达温柔和爱意。然后一来二去,性和爱互相交织,慢慢的就无法再分清楚彼此了。</p></blockquote><blockquote><p>上帝造人时是故意要这样设计的:把男性的生殖器设计成外挂型的,让它可以随时方便地和外界接触;也正是由于男性的生殖器是外挂型的,使得它常常可以摆脱男性的意志而独立选择要不要“探出头”去。而女性的内置型的生殖器则让女性可以选择只对自己喜欢的男性开放,且可以自由控制是否要开放它。</p></blockquote><blockquote><p>刚出生不久的男婴就会有阴茎勃起的现象,待他们能够手眼协调,就会有自慰的行为。这种对性的好奇与兴趣,要差不多到五六岁才会消失(被其他事物吸引),然后,性的能量在青春期才会重新启动。</p></blockquote><p>第<strong>5</strong>章 女人为什么会这样?</p><blockquote><p>没有不想做小女人的女人,只有没机会做小女人的女人。</p></blockquote><blockquote><p><strong>女人爱涂口红的原因:</strong> 众所周知,性高潮后的女性是最美丽、迷人的,而涂抹了红色唇膏的嘴唇,其实是对性高潮的一种模仿。</p></blockquote><blockquote><p><strong>女人爱穿高跟鞋的原因:</strong> 高跟鞋能使女性的小腿线条显得修长,身材更挺拔,胸部更突出。由于高跟鞋的不平衡,女性走起路来会不由自主地扭腰摆臀,性感便在这些身体语言里若隐若现了。 穿着高跟鞋会让女性缩紧会阴和下腹部的肌肉,进而提升性能力。</p></blockquote><blockquote><p>“美不美,男人看了就知道;好不好,女人听了就知道”。</p></blockquote><blockquote><p>脾的功能和肌肉的状态密切相关,也就是说,如果一个人的脾脏比较弱,肌肉也就表现为松弛无力。 中医说“思伤脾”,意思是说一个人思虑得太多,就会伤及到脾。这就意味着常常勤于思考,且情绪、情感非常丰富的知识分子,如果想要得到一身健硕的肌肉,是比较难的。</p></blockquote><blockquote><p><strong>女性的乳房:</strong> 女性乳房的平均重量为0.5千克,占人体总脂肪的4%—5%。公认最美的乳房是半球形、水滴状,位于女性第2—6肋骨间,同时乳头位于第4肋骨间。乳房基底面值直径为10—12厘米,乳轴高度为5—6厘米,乳晕直径为3.5—4.2厘米。 同一个人在不同的年龄阶段,乳房的大小和形态会有明显不同。年轻女孩的乳房由脂肪、乳腺和胶原质组成,所以显得坚挺;随着年龄的增长,乳腺和胶原质会被脂肪所代替,过多的脂肪会导致乳房的下垂。</p></blockquote><p>第<strong>7</strong>章 那些鲜为人知的性少数人群</p><blockquote><p><strong>S-M,</strong>即Sadism,译作施虐癖;M,即Masochim,译作受虐癖。这两个词语出自专写虐恋题材的两个作者的名字,前者是法国贵族萨德侯爵(Marquis de sade),喜欢对女性施以虐待以达到性满足;后者则是奥地利作家马佐赫(Lepold von Sacher-Masoch),他喜欢在性活动中被动虐待而达到性满足。</p></blockquote><blockquote><p>异性恋者歧视同性恋者,同性恋者歧视双性恋者,双性恋者歧视变性人。</p></blockquote><blockquote><p>有人猜测,男人很可能都是女人“变”的。证据之一,是男人之所以也长有无用的乳头。因为胚胎在8周之前无法确定自己的性别(所以每个胚胎最初都准备了两套生殖系统,即中肾管和副中肾管),为了不错过发育的时机和进程,只好把乳头也一起发育了。到了第8周,有部分携带Y染色体的胚胎在大量睾酮素的作用下选择了男性生殖系统,“变成”男胎儿,而另外那些没有Y染色体的胚胎则因为没有被睾酮素“干扰”,从而继续发育为女胎儿。</p></blockquote><blockquote><p>在生活中,这种专业形象在一定程度上会让人有压迫感。那么,在有些人的性幻想里,就总希望打破或毁坏这些固化了的形象,就像是挑战或跨越权威和秩序,从而获得某种心理上的胜利感和成就感。同时,这也是一种可以伴随着性幻想而获得强烈性刺激的方式。</p></blockquote><p>本来是不想发这篇书评,因为心里其实是有些放不开的。但是我整理的这份在「微信读书」里获赞颇多,现在想是不是有必要把它分享出来,让更多的人看到,也算学习了吧。</p>]]></content>
<summary type="html">
<p>在正式开始话题之前,我想讲讲我的性启蒙。</p>
<p>关于这件事儿,认真追溯起来竟然没有某个特别值得纪念的日子或事情。只是模糊记得一些场景,使得这个世界上的一个普通的孩子经历了神奇般的体验。</p>
<p>那时的我,不知道 AV 为何物,黄也只是一种看起来感觉暖暖的颜色,
</summary>
<category term="书评" scheme="https://blog.yanng.io/categories/%E4%B9%A6%E8%AF%84/"/>
<category term="书评" scheme="https://blog.yanng.io/tags/%E4%B9%A6%E8%AF%84/"/>
<category term="性" scheme="https://blog.yanng.io/tags/%E6%80%A7/"/>
</entry>
<entry>
<title>问题之书</title>
<link href="https://blog.yanng.io/2016/12/28/wenti/"/>
<id>https://blog.yanng.io/2016/12/28/wenti/</id>
<published>2016-12-28T00:40:54.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>文 | 王前</p></blockquote><h4 id="我们所需要的,只是看清自己,这么简单。"><a href="#我们所需要的,只是看清自己,这么简单。" class="headerlink" title="我们所需要的,只是看清自己,这么简单。"></a>我们所需要的,只是看清自己,这么简单。</h4><p><strong>先正确评判自己,才有能力评断他人。</strong></p><p>每个清晨和太阳一同醒来,自己能否对发生事情做出理理性的判断?</p><p>能否理性但不苛求,温柔但不软弱,敢于讲真话,表达自己的立场?</p><p>能否在犹豫的时候,用初心提醒自己不要迷失?</p><p>能否在勇敢踏出第一步之后,发现世界那么大,还要走很远的坚守?</p><p>能否在冗长的坚持和守望中,虔诚的,道德服从的,绅士的,乐于助人的,忠于内心的,一路向前,一路行走?</p><p>能否在承受压力时不让自己落入平庸?</p><p>能否在承受生命之轻时,试着去放空自己,体验生命本身的厚重?</p><p>能否尊重眼泪,先让那个向上的心足够强大,再让那个最好的自己释放本心的坚韧?</p><p>能否只重视生命里吉光片羽的阳光,完全忘掉美景背后的一大堆影子和黑暗?</p><p>能否克服自身相互斗争的因素,安静地、笃定地朝着心之所向从事各种活动?</p><p>能否让那一腔活着的热情在不时之需温暖自己和他人?</p><p>能否用心灵的上善若水和丰衣足食,为别人提供一个良善的视角去看待世界?</p><p><strong>你是否欺骗别人,或是自己?想清楚再回答。</strong></p><p>在这个世界上,每个人都有一块必得由我们自己来耕种的土地,种春风得春天,种荒草得荒原,请务必记得,所有的良善的希望,决不比任何一个智者的希望更谦卑。</p><p>先要对自我忠诚,明白自己的本心,明确自己的需要,制定可行的计划,然后再放开了大胆主动地行动,好过软弱被动到活着。</p><p>坦诚相待,也是对彼此的尊重和欣赏,矫揉造作的伪饰,相比一句发自内心的赞美,轻如鸿毛。</p><p>只有去伪存真的东西,才经得起时光的打磨。 能否理性得对待世界,超过感性地去爱自己?</p><p><strong>先要学会独立思考,才能独立去做事。</strong></p><p>能否甘于寂寞?</p><p>能否让寂寞播种安定,使安定萌发心静,使心静开出像早晨一样清白明亮的花来,指引你明白一切事理?</p><p>能否在青春的大冒险里,一个人勇往直前也能愿赌服输?</p><p>能否听取别人的意见,尊重别人的自由的意志,独立地做出决定?</p><p>能否随时用空杯的心态去迎接风雨,像拥抱太阳那样义无反顾?</p><p>能否找到属于自己的方向,从一而终而非一时兴起?</p><p>能否从成长的象牙塔里勇敢地突破自我,挑战自我,快乐地发现隐藏版的自我?</p><p>能否就算是被谁从云端推落,也能拥有好好地用心地看清楚整片天空的胸怀?</p><hr><p>我们所需要的,从来都不是在嘈杂的世界里迎合任何的眼光和脸面,而是那个心里建设的自我,能否成为那个一心向上的自我的保护色。</p><p>能否在一方静好无常的土地上,带着金砂一般渺小而闪光的品质,为世界的前行慷慨解囊?</p>]]></content>
<summary type="html">
<blockquote>
<p>文 | 王前</p>
</blockquote>
<h4 id="我们所需要的,只是看清自己,这么简单。"><a href="#我们所需要的,只是看清自己,这么简单。" class="headerlink" title="我们所需要的,只是看清自己
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="文章" scheme="https://blog.yanng.io/tags/%E6%96%87%E7%AB%A0/"/>
</entry>
<entry>
<title>苹果的偏执</title>
<link href="https://blog.yanng.io/2016/12/14/apple/"/>
<id>https://blog.yanng.io/2016/12/14/apple/</id>
<published>2016-12-14T02:23:58.000Z</published>
<updated>2018-07-05T10:20:27.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>最近在知乎上看到一贴有关「苹果有哪些黑科技」的回答。本来想找作者授权转载,可惜作者用了匿名回答。知乎上这篇原贴已经被作者删除,但还是以图片的形式留了下来。通篇看下来,我认为名字改为「苹果的偏执」更恰当一点。 我用了多半天的时间将图片中的文字摘录下来,并逐字进行校对订正,来完成这一篇有意思的文章。 这篇文章对于我这个果粉来说,看完更加了解了 Apple 对产品的苛求。 Apple 每款产品的火爆并不是靠运气,而是极其严谨甚至达到了死磕的境地(抛去苹果的营销策略单说产品这块儿)。这篇文中所述真实性有待考证,但我相信 Apple 确实可以做到。</p></blockquote><hr><p>在不泄密的前提下,我来讲几个八卦吧,算不上黑科技,算是苹果的做事风格。</p><p>1、</p><p>某款产品的主板非常迷你,上面的元器件密度很高,因此用于主板测试的接口只有绿豆大小。 proto 期间需要设计一款测试软线(FPC)接到这个接口上测试板子状况。这是技术背景。</p><p>因为接口太小了,软线上的 pin 脚密密麻麻,设计公差只有 +/- 0.01 毫米,也就是说尺寸大一点,小一点或者位置偏了 0.01 毫米,这根线就没法用,甚至会把板子直接短路烧掉。测试线一般都是由代工厂自己准备的。代工厂找了好多家 FPC 厂商来做这根测试线,每个厂家都反馈说做不了,精度没法控制这么高。</p><p>代工厂没办法,找 Apple 汇报这个情况,问能不能把测试端口做大一点, Apple 说你别管了,这根线我们自己做吧。</p><p>十多天后,两根合格的测试线送到了代工厂,在场的电子工程师们由衷赞叹苹果的黑科技。</p><p>至于是怎么做出来的,这事我清楚:苹果找了一家 FPC 厂商,一口气生产了 2000 多根线,然后挨个在板子上试,最后挑出来好用的一共就这两根。当时的计划是如果挑不出,再做 2000 根…</p><p>所谓真正的高科技都来自于简单粗暴…</p><p>故事还没完,两根线送到了代工厂,开始生产的时候,第一个产品送到站上,操作员拿起一根线,随手抻了一下,断了…</p><p>在场围观的工程师们瞬间发出一阵哀嚎。</p><p>剩下的一根独苗成了整个产线的宝贝,操作的时候比动外科手术还珍贵,那个毛手毛脚的操作工打发他去仓库搬箱子去了。</p><p>好在剩下的那根线挺到了 build 最后也没有坏,不然因为这个停线就糗大了。</p><p>2、</p><p>Apple 另一个精密产品的组装,具体多精密就不细细描述了,总之图纸上标注的公差严的不讲道理。除了设备要极其精密以外,操作手法也很讲究按技巧。试生产了一段时间,发现整个代工厂只有一个操作工人可以把这个活做好,换个人良率就降下来。当时苹果就指定,这个工站的这个操作,只许这个工人做,代工厂没有得到批准不许换人。</p><p>但是规定这东西,放在纸面上还可以,怎么执行就没那么简单了。这个工人请假怎么办?临时有事怎么办?迟到怎么办?产线不忙的时候,被调去别的线上操作,这边开线了一时间回不来怎么办呢?代工厂不愿意停线等人,停线一小时损失可是以万计。</p><p>于是这个规定没有被很好的执行下去,有一天发现良率很差,一调查,代工厂那天换了个人操作那个关键工站。</p><p>苹果的 TPM 很生气,但是后面怎么管理成了难题。毕竟苹果 audit 严线的 PM 也经常换人,不认识这个操作工,工厂自己换人也查不出来。</p><p>最后的解决方案,是把这个工人的大幅高清照片帖到这个工站最显眼的位置,只要 Apple 的人在线上发现人跟照片不一致,马上命令停线。产线上贴照片这种事,真是第一次见。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>3、</p><p>某南方代工厂用的一款重要的双面胶经常出问题,一调查,发现仓库里有老鼠。老鼠不知道为啥特别中意这款双面胶,存货经常被咬的惨,只能报废。</p><p>本来以为只是仓储的事情,代工厂自己搞定就好,没想到类似的事情一而再而三发生,一调查,仓库除鼠是世界性难题(好吧,至少在中国还没有好的解决方案,仓库在建的时候就不是全封闭的)。看代工厂搞不定,然后苹果又介入了,找了一个实习生安排解决这个问题,实习生制定了一套方案,方案的核心很简单,在仓库派人养猫。</p><p>看过这个方案的人第一反应都是,不是在搞笑吧?!</p><p>详细规定了用什么猫,多大年龄,品种是什么,养几只,采购预算多少,采购途径怎么走,如何考核猫的绩效,退役年龄多大。</p><p>还规定了猫的各项福利,吃喝拉撒加退休都包含在内,养猫人的工资算做产品的成本。猫怎么样才能保持好心态,积极主动工作都考虑在内。</p><p>苹果的黑科技就是注重细节,后来这个仓库的鼠患彻底没了。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""> 能抓到老鼠的就是好猫</p><p>(图片来自网络)</p><p>4、</p><p>说到苹果,除了设计团队之外,必须要讲一讲同样牛逼但是不被大众了解的运营团队。</p><p>苹果的 TPM (负责生产技术)和 SQE (负责产品质量)确实很牛,一线的工程师都是从国内各个大公司来经理级的人物来做小兵的活儿。本来资质就够硬,加上苹果多年文化的熏陶,对于制程,良率的理解的控制可谓出神入化。</p><p>新供应商的导入模式通常是,一个没有做过草果产品的供应商开始给苹果供货,因为苹果要求太严,往往开始的良率都在 30~50 % 之间,根本不赚钱。然后苹果会派一个 TPM/SQE 驻厂,专心研究生产流程和质量控制中的问题,疯狂加班一个礼拜各种改善,然后这个工程师人。这时候良率一般就会被提到 90% 以上。</p><p>很多公司愿意给草果做供应商,虽然价格和员工被压控的很惨,但是做完一个苹果的项目作为洗礼整个公司的技术/管理水平会整个提高一个档次。跟苹果做过项目的人都知道我在说啥。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>iPhone 回收机器人 Liam</p><p>(图片来自苹果)</p><p>5、</p><p>前面提到了实习生。跟很多硅谷公司一样,苹果常年会招聘一批突习生工作,这些人都是斯坦福,加州伯克利,MIT 这些名校的硕士博土,都是学霸中的学霸。实习生来到公司以后,常常会安排一个并不迫切需要的课题,让他自由发挥,试一试做下去能做多深。</p><p>大概06,07年的时候,有个突习生来到苹果的 Mac PD 组,当时的 MacBook 还是用塑料壳,给他的课题是研究一下,如果纯用铝 CNC 加工来做笔记本外壳,可行性如何。几个月后,这个实习生拿出来非常接近量产的 Uniboby 铝壳样品。轻巧,结实,美观,直接把大家镇住了。随后乔帮主拍板做 Unibody,也就有了后来的 MacBook Air ,间接影响了后面的 iPhone , iPad 的设计。</p><p>这个人是我知道的最牛的实习生,名叫 Keith ,结束实习后顺利留在苹果。现在用的新一代的键盘也是他设计的。如果你打开苹果网站 New Macbook 的宣传视频,在介绍 butterfly 键盘的时候,键盘上模拟有人按键,键帽依次打下来的字是:Hello Keith。</p><p>全新 MacBook 产品介绍</p><p>(视频来自苹果)</p><p>6、</p><p>很多人知道 iPhone 引导了后来智能手机的设计语言,其实就生产制程来说又何尝不是如此。现在金属件的 Unibody 在电子行业算是非常主流的设计,但在苹果使用这个设计之前,消费电子产品里,压 CNC 加工金属十分罕见。</p><p>原因在于成本和效率。那个时候 CNC 的种类,连带其刀具的种类非常有限,可供加工的特征都是些简单的孔槽之类。但当苹果开始进入这个领域,花了大价钱和精力研究 CNC 制程,以加工复杂的成型面和提高精度,大笔的钱砸下去,基本每个特征专门研究一个刀具和制程。用业内人的话说:苹果用一己之力发展了铝壳 CNC 这个工业学科。</p><p>在 MacBook , iPad , itouch 这些产品成功量产以后,随着技术的扩散,Unibody 才开始被大家玩的烂,铝壳一体成型 CNC 也不再是富土康垄断的高端技术。</p><p>除了给一大堆 CNC 设备厂商带来了春天之外,苹果用心研发,把一些当时虽然有但无法量产的技术应用到消费电子产品上,包括激光焊接,CCD 辅助装配,各类光学测量设备,胶水在电子产上的使用(点胶)等等,相关厂商都赚的盆满钵满。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>7、</p><p>现在 MacBook 上用的 USB type C 是纯正的苹果设计(即为 MacBook 设计的 Thunderbolt 3 )。但为了向市场更快普及,借助 intel 以 USB type C 的名义发布。设计这款接口的团队也设计了 lightning , Magsafe , Thunderbolt 这些非常优秀的接口。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>8、</p><p>苹果的当家吸金 iPhone ,其实是一群不懂手机设计的人设计出来的(这里只讲硬件)为啥这么说呢。iPhone 刚出来的时候,答主已经在手机设计行业做了多年,国内凡是做手机的厂商,打开壳子一看,设计思路就是两条;Nokia 式的和 Moto 式的。Nokia 偏整体,板子上器件都直接焊死,各种壁厚,卡扣都往大里做,好处是够结实,缺点是维修性不好。Moto 式相反,拆卸性好,部分模块化设计,错落有致,但是没那么重视可靠性。国内做结构设计的最早那批人,都是从诺基亚/爱立信,或者 Moto 跳出来的,所以当时每个手机厂商的设计,都深深打下其中一个流派的烙印。夸张点讲,一看你做的卡扣尺寸形状,我就知道你是哪一派的。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>iPhone 一出来,拆机一看,完全把我和我的小伙伴镇住了,完全是不懂手机设计啊!以当时的标准( 2007 年)来看,犯了 N 多忌讳:</p><p>电池没有居中(导致重心不居中,当时的设计迷之信心对体验的影响)。</p><p>接口没有塞子(当时只要设计手机,都要给数据接口做一个橡胶塞,除了防水防尘,也为了美观)。</p><p>没有设计挂绳孔。</p><p>正面全玻璃,一米左右就有可能摔碎,让人怎么用?</p><p>不能换电池。</p><p>没有可拆卸的电池盖(或其他任何形式的盖子),这个之所以重要,是因为当时国内的法律规定,任何手机都要至少贴两个标签:入网标签和产品标签(电子产品 3C 认证)。而且这两个标签必须贴到产品本体上(不能帖到包装盒里或者电池盖这种容易更换的部件上)。没有电池盖就意味着要么你的标签不能藏在盖子下面,只能贴在手机外面(丑)。要么就不能在国内卖(欧洲也有类似的要求)。苹果直接把产品信息雷雕到背盖上,至于入网标签和产品标签…呵呵…</p><p>因为没有中壳,所有的元器件的定位组装方法都要重新设计。</p><p>基本不用卡扣,全靠螺丝和胶带。</p><p>没有物理键盘。(欧盟当时强制要求手机要有物理按键,为了是紧急情况下可以盲操播出求救电话。)</p><p>手机卡不是标准形状。</p><p>所有的接口都用钢片螺钉固定。所有的侧键都用钢片螺钉固定,所有觉得需要加强的地方都用钢片螺钉固定,完全不计成本和组装效率。</p><p>Home 键的组装设计:当时所有的侧键都必须与外壳留足 0.3 mm 的间隙,为了保证组装公差且不会卡键。但 iPhone 的 Home 键间隙只有 0.03 mm ,至于怎么组装的涉及到当时还不流行的 CCD 定位。以后再补充。</p><p>设计 iPhone 的 PD( Product Designer )是一群天才的工程师,他们完全不理会市场上现有的手机设计经验,用大学毕业生的思路来解决各种设计和技术问题,在 iPhone 上我们看到的是最直接的思路和最简单的解决方案,简直像是把爱因斯坦,牛顿,麦克斯韦这些人拉过来,拿枪逼着他们做出来的一款手机,最后能搞出来的样子。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>9、</p><p>科技类新闻网站往往喜欢报道一类新闻:苹果最近申请了什么什么技术的新专利,然后据此预测下一代的产品会有什么大动作,云云。</p><p>实际上,所谓的专利,本质上是以公开换保护,在专利认证过程中技术细节也会一并公开。然而苹果最看重的是封闭跟保密,对于将要使用的技术永远不会申请专利(等于在上市之前公开设计细节。)而申请专利的技术都是把目前不会使用东西在法律上占个坑。因此可以总结出两个凡是:</p><p>凡是能在专利网站上看到的苹果申请专利的东西,苹果下一代产品都不会应用。凡是苹果认为牛逼的技术,在技术壁垒随时间消失之前,苹果都不会拿去申请专利。</p><p>至于有人质疑,如果自己不申请专利,导致专利被人抢注了怎么办?在专利法中有一条原则,如果使用专利的一方可以证明这项技术在你申请专利之前就已经在使用了,那么可以要求法院判定你的专利无效(新颖性原则)。举个例子:你没办法在一家饭店吃到一个好吃的酱料,然后把配方注册成专利,然后反过来要求这家饭店缴纳专利费。</p><p>此原则同样适用于外观专利,中国公司可以抢在苹果前面在国内注册新 iPhone 的外观专利,但是苹果只要拿出早先研发阶段的证据证明原型机早于抢注,就可以申请被抢注的专利无效。</p><p>10、</p><p>之前的 iPhone 新机型之所以不在中国首发,是出于保密的原因,至于网上说的,不在中国首发,是因为工信部认证太慢,这个说法既对也不对。</p><p>以第一款在国内首发的 iPhone 5s 为例,苹果 9 月份发布,但成熟的量产机型在 4 月份左右就已经生产出来了。而工信部认证需要大概三个月,因此想在国内首发,只要六月份之前把手机交给工信部的实验室就可以了。</p><p>然后那年就发生了史上最严重的 iPhone 泄密事件之一:手机前脚交给工信部,后脚全套照片(主要是曝光了新机型 iPhone 5c )和新版 iOS 的界面就在网上曝光了,显然是工信部内部的测试员拍照流出来的。</p><p>以往供应商层面的泄密虽然难以预防,但是往往是零件级别,整机照片很少泄露,尤其是能点亮的装好系统的整机这是第一次。于是高层震怒,但工信部自己没义务替你保密,于是苹果决定再也不在手机发布前把样机送交工信部。</p><p>所以后面机型的套路就是,产品在美国发布的当天,把 iPhone 提交工信部,然后三个月后认证结束在国内上市,也就必然赶不上首发。(但 iPhone 6s 是特例,因为外观几乎没有改,iOS 也不是随机器更新的。为了销量,当时就把 6s 提前送测了。后来果然也泄密了)</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>至于 iPhone 7 为什么能在中国首发,这就真是苹果的黑科技了:</p><p>工信部管理阶层其实还是蛮有节操,倾向于遵守协议,替苹果新品尽保密的义务的。但是他没有办法约束具体的办事人员。要想达到苹果需要的保密标准,需要在实验室内外安装全套的安检设施:窗户封死,进来不得带任何电子产品,出去的时候不能带走一片纸,实验室的电子锁和警报装置要全年 24 小时待命(实验室里面反而不许装摄像头,原因后面再讲),进来的人要签保密协议,被搜身。连实验室卫生打扫,防火设施,垃圾处理都有严格的规范。</p><p>就算工信部愿意帮你保密,也不可能为你一个公司设置这么多设备人员和工作流程,就算你出钱也不行,我们工信部好歹是正规部委,能让你这么折腾?</p><p>苹果的解决方案是:在工信部附近买了一栋楼,建了一个实验室,凡是工信部实验室里有的设备,同释型号同样规格这里也买一份,连房间布局都是一模一样的,然后把安保设施做好。需要 iPhone 认证的时候,iPhone 放在这个实验室里,把工信部的操作员请过来在这个实验室做检测,手机不带走。</p><p>这才有 iPhone 7 国内首发,而且可看到的未来 iPhone 都有能力在国内首发。</p><p>11、</p><p>继续讲保密,iPhone 7 的一个零件供应商因为泄密事件按协议赔了 500 万人民币,泄密的内容很扯蛋,每个工站上有该工站操作的流程图(俗称 SOP ),上面有图片标注应该把什么零件按到什么部位。有个操作员把这张流程图愉偷取下来带走,卖给媒体,图上有 iPhone 的半成品照片。</p><p>这下闹大了,因为是直接从厂里泄密。苹果安保反思怎么杜绝这个问题:现有的安检技术根本没有办法检查到工人带一张纸离开车间。</p><p>解决方案也很苹果:产线上所有的 SOP 全都改用含金属材料的纤维印刷品制作…看你怎么带出去。</p><p>12、</p><p>苹果代工厂的关键设备,主要是自动组装,CNC ,激光焊接,CCD , AOl 自动检测这些,都是苹果出钱购置的。项目结束这些设备要么报废要么收走,不会留给代工厂,因为担心代工厂会用这些设备为竞争对手做类似的产品。</p><p>但是管的了设备管不了技术啊,代工厂都很聪明一旦学会了一个工艺,再帮别家公司做 ODM 设计的时候,总归知道该怎么搞了,这方面实际上防不住。(不要提专利,专利只保护实现的方法不保护工作原理和达到的结果。具体工程里面,很多专利换个方法就绕过去了。)</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>因此另一个比较蛋疼的苹果特色是,最新的产品研发不找最大/最专业的供应商。</p><p>比如苹果之前所有的键盘都是找达方,Sunrex 这些世界一流专业键盘厂来代工的,但这些厂不仅给苹果做键盘,也给戴尔,联想,惠普这些公司做。当苹果设计出 butterfly 键盘以后(也就是苹果现在笔记本电脑上的键盘),找的代工厂是一家不以键盘为业务,从来没做过,未来也不会给别人做键盘的公司(名字不讲了,你们不会把这家公司跟键盘联系起来的)。代工厂没做过键盘,对于研发是件极其痛苦的事情,良率低,成本高,速度慢,新一代蝴蝶键盘的生产简直就是悲剧。但是,现在市面上也没有任何一家竞争对手有能力跟进,未来五年内我相信也不会。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="">苹果带 Force touch 的触摸板也是同理,猜猜代工厂是谁?</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>13、</p><p>苹果新出了一本产品图册《 Designed by Apple in California 》,定价小两干。知乎上一堆人骂,自己的广告册还好意思卖这么贵。</p><p>我想讲的是,就算印本书,也体现了苹果的黑科技(=砸钱)。</p><p>不提原材料有多贵,单讲印刷厂。这本书的代工厂是深圳雅昌,一家极其高大上的的艺术品中心,他们的主营业务是给各类著名艺术家,画家印刷制作作品图册,通常的一个产品的印刷术也就三五百本。他们是搞艺术的不屑于做量产,也不把钱着在眼里,不愿给苹果做——因为苹果的量太大,严重占用了他们的产能。</p><p>所谓产能,就是高精密的印刷机,全国除了他们家应该没有其他商业组织有了(待考)。这种印刷机精度级别可以印钞票,因此需要接受政府登记监管,数量也十分有限,不能随意扩大产能。</p><p>苹果看中了这几台设备,死磨硬泡要雅昌代工图册,说起来很蛋疼,据我所知这是第一次苹果求供应办事。最后之所以能搞定,还是砸钱砸出来的:单本的出厂价我就不透露了,这么说吧,以这个成本,去掉税费,苹果的这批图册,卖一本赔一本。</p><p>即便如此,雅昌还是很后悔接了这个单。前面说过,这个艺术公司根本不是为了赚钱作为目标(苹果最怕这种公司)。他们为苹果制作图册,每生产一万本(具体多少不能讲)就意味着要拒绝几十单老客户的需求,让大牌艺术家为电子产品图册让路,得罪了关系户,得不偿失。</p><p>所以第一批订单搞完以后,苹果想要继续追加产量,雅昌直接拒绝,现在还在谈判。所以想买这图册的人的赶紧下手吧,搞不好就是绝版。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>(视频来自苹果)</p><p>14、</p><p>前面讲过 SOP ,用金属纤维布制作产线 SOP 图还不是最烧钱的。在 MacBook 产线上,每个工站上放了一个 iPad Air 显示该站的 SOP,显示效果清晰而且可以随时更新,还有动画效果更容易新手理解。一条线几百个工站,乘以 N 条线。这钱烧的。。</p><p>在松江广达,每个工站上挂一台 iMac,只是为了显示 SOP,堪称史上最贵操作说明。</p><p>15、</p><p>讲一个很多业内人都知道的吧,苹果首创的组装技术。</p><p>现代大规模制造的一个基本原则,就是通用性,如果两个零件需要装配到一起,那么分别生产一百万个零件 A 和一百万个零件 B ,任何一个 A 和 B 都应该可以组装到一起。</p><p>这就带来了一个问题,比如一个按键要组装到按键孔里面去,那么按键一定要比按键孔小。但是你生产加工一百万个按键和按键孔,每个都有大有小所以必须保证最大的按键要比最小的按键孔还要小,这就是所谓的公差设计。这种设计的结果是,平均尺寸的按键跟按键孔之间在设计的时候必然预留有一个缝隙。假如按键跟按键孔的精度分别能做到 +/- 0.1 mm ,你的按键间隙也会在 0 ~ 0.4 mm 之间。</p><p>苹果讨厌间隙,因为外观看起来不高档,从 iPhone 5 / 5s开始引入了组装新工艺:iPhone 5 / 5s 背后上下两片陶瓷装饰片,他们与外壳的间隙是 0 ~ 0.03 mm,用传统工艺根本做不到。</p><p>具体做法是,每当一个产品流到陶瓷片组装的工站时,会有摄像机对这个孔拍照测量,计算出孔的尺寸(因为这个形状不是基本的圆或直线几何形状,测量的其实是 profile 。)。然后机械手从装满陶瓷片的库里面挑逃出一片跟这个孔尺寸最接近的产品,安上去。这样就能保证每个产品的间障做到最小。这套设备在当时是天价。但是大家觉得值,很多产品看起来差不多,但是苹果的拿在手里就是显得高档,就体现在缝隙,台阶,颜色这些细节里。</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p>16、</p><p>苹果充电线因为容易破损,被无数人吐槽。之所以做不到很结实,主要原因在于原材料要同时满足洁白颜色(外观),不含卤素(环保),高防火等级(安全)三个要求。其实只要放松任何一个的要求,都可以做的很结实。现在的线材是满足条件下强度最好的材料。</p><p>另外,在苹果产品定义里,线材属于消耗品,你能一年换一件衬衫,一年换个充电线有什么不妥?</p><p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt=""></p><p><strong>end</strong></p>]]></content>
<summary type="html">
<blockquote>
<p>最近在知乎上看到一贴有关「苹果有哪些黑科技」的回答。本来想找作者授权转载,可惜作者用了匿名回答。知乎上这篇原贴已经被作者删除,但还是以图片的形式留了下来。通篇看下来,我认为名字改为「苹果的偏执」更恰当一点。 我用了多半天的时间将图片中的文字摘录下来
</summary>
<category term="碎碎念" scheme="https://blog.yanng.io/categories/%E7%A2%8E%E7%A2%8E%E5%BF%B5/"/>
<category term="文章" scheme="https://blog.yanng.io/tags/%E6%96%87%E7%AB%A0/"/>
<category term="Apple" scheme="https://blog.yanng.io/tags/Apple/"/>
<category term="偏执狂" scheme="https://blog.yanng.io/tags/%E5%81%8F%E6%89%A7%E7%8B%82/"/>
<category term="工业设计" scheme="https://blog.yanng.io/tags/%E5%B7%A5%E4%B8%9A%E8%AE%BE%E8%AE%A1/"/>
<category term="苹果" scheme="https://blog.yanng.io/tags/%E8%8B%B9%E6%9E%9C/"/>
<category term="黑科技" scheme="https://blog.yanng.io/tags/%E9%BB%91%E7%A7%91%E6%8A%80/"/>
</entry>
</feed>