Fork me on GitHub
那些踩屎的经历

修煉中..


  • 首页

  • 关于

  • 归档

  • 标签

  • 搜索

JavaScript 事件循环笔记

发表于 2019-01-24 | 分类于 js

Javascript 的单线程保证所有的任务都按照一定的规则顺序排队执行,这个规则就是 Event Loop 事件环。

[事件循环]
  • 主线程运行时,JavaScript 会产生堆和栈(执行栈)
  • 主线程调用 webApi 产生的异步操作只要产生结果就塞入“任务队列”等待执行
  • 主线程同步任务执行完毕,读取“任务队列”中任务放入执行栈执行
  • 执行栈执行过程中会产生新的异步操作,产生新的循环
阅读全文 »

原型、原型链笔记

发表于 2018-12-31 | 分类于 js

解释:为了共享多个对象间的一些共有特征(属性或方法)

JavaScript 中的对象,都存在一个内置属性[[prototype]]也做 __proto__,指向这个对象的原型对象

js 中查找一个属性或方法,如果当前对象无定义会继续查找当前对象的原型对象,如果仍未找到,会继续查找原型对象的原型。如此直至最顶层的原型对象,如果仍未找到返回 undefined

最顶层的原型对象 为 Object.prototype, 里面保存了最常用的 toString、valueOf、hasOwnProperty 等方法,故任何对象都可以开箱即用。

创建对象的三种方式

1. 字面量方式

字面量方式创建对象,它的原型就是 Object.prototype

1
2
var obj = {};
obj.__proto__ === Object.prototype // true

2. 函数构造调用

Js 在定义一个函数时,同时为这个函数定义了一个默认的 prototype 属性, 所有的共享的属性或方法都被放到这个属性指向的对象中。

由此看出,通过一个函数的构造调用创建的对象,它的原型就是这个函数的 prototype 属性指向的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 创建构造函数
function Person(name) {
this.name = name;
}
// 每个构造函数,js 都会为之自动添加一个 prototype 属性,称之为原型,是一个对象
// 每个构造函数创建的对象都会共享 prototype 上面的属性与方法
console.log(typeof Person.prototype); // 'object'
// 为 Person 添加 sayName 方法
Person.prototype.sayName = function() {
console.log(this.name);
}
// 创建实例
var person1 = new Person('a');
var person2 = new Person('b');
person1.sayName(); // 'a'
person2.sayName(); // 'b'
person1.sayName === person2.sayName // true
阅读全文 »

React+webpack4+Babel7 脚手架搭建过程(二)

发表于 2018-12-20 | 分类于 react

第二篇主要是 react react-router react-redux

React

1
2
## 安装 react && react-dom
npm i -s react react-dom
1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import ReactDOM from 'react-dom';
if (module.hot) {
module.hot.accept();
}
ReactDOM.render(
<div>Hello React!</div>,
document.getElementById('root'),
);

运行可见 Hello React!

React-router

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
// install react-router-dom
npm i -s react-router-dom
`cd src`
`mkdir router && touch router/router.js`
// router.js
import React from 'react';
import {BrowserRouter as Router, Route, Switch, Link} from 'react-router-dom';
import Home from '../containers/Home';
import Page1 from '../containers/Counter';
const getRouter = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/Counter">counter</Link></li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/Counter" component={Counter} />
</Switch>
</div>
</Router>
);
export default getRouter;
// 修改src/index.js
import React from 'react';
import ReactDom from 'react-dom';
import getRouter from './router/router';
ReactDom.render(
{getRouter()}, document.getElementById('root'));
阅读全文 »

React+webpack4+Babel7 脚手架搭建过程(一)

发表于 2018-12-19 | 分类于 react

第一篇主要是 webpack babel eslint

webpack

首先新建个空的文件夹并通过 终端进入(后续所有操作基于终端)

1
mkdir quick-start && cd quick-start

Webpack 的安装需要借助于 npm ,所以我们您需要创建一个 package.json

Package.json 是一个标准的 npm 说明文件,里面保存着当前项目的基本信息,项目依赖以及自定义脚本任务等。

终端中使用 npm init 命令创建 package.json

执行 npm init 命令依次输入项目信息,或者直接 npm init -y 跳过这些信息的输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
npm init -y
## 执行后得到如下信息
{
"name": "quick-start",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

准备工作完成,开始安装 webpack

webpack 4之后分成了 webpack 以及 webpack-cli 两个依赖,所以我们依次安装

1
npm i -D webpack webpack-cli

接下来我们需要 创建一些文件和文件夹

当前目录下创建 src dist​ 两个文件夹 并在 src 里面创建两个文件 index.js index.html

1
mkdir dist src && touch src/index.js src/index.html
阅读全文 »

执行上下文和执行栈

发表于 2018-12-08 | 分类于 javascript

又来过基础

执行上下文

什么是执行上下文

Execution Context(执行上下文)就是定义变量或函数有权访问的其他数据,并决定了他们的行为。
根据所在环境的不同一共有三种类型:

  • 全局执行上下文
    默认、最基础的执行上下文,且一个程序只能存在一个全局上下文
  • 函数执行上下文
    每次 调用 都会创建一个新的执行上下文
  • Eval 函数执行上下文
    运行在 eval 函数内的代码有着自己的执行上下文

执行栈

先进后出的结构,用于存储代码执行期间创建的所有执行上下文
JavaScript 引擎开始读取脚本时,先默认创建一个全局执行上下文并将其推入栈底,每发生一个函数调用,引擎就会为该函数创建一个新的执行上下文并压入栈。引擎会运行处于执行栈栈顶的函数,运行完后,其对应的上下文从栈中弹出,交还控制权给当前执行上下文的下一个执行上下文

1
2
3
4
5
6
7
8
9
10
function foo(y) {
var sum = foo1(y) + 1
console.log(sum)
}
function foo1(x) {
return x+1
}
foo(5)

执行栈简图如下:
QQ20181208-174019@2x.png
注:每次函数调用都会创建新的 执行上下文,哪怕是递归调用

执行上下文的创建

执行上下文分两个阶段创建: 1)创建阶段 2)执行阶段

创建阶段(函数被调用,代码未执行)

1. 初始化作用域链
2. 创建变量对象
3. 创建参数对象,检查参数上下文,初始化其名称和值并创建一个引用拷贝
4. 扫描函数声明,对于未发现的函数在变量对象中创建一个同名属性,如果已经存在的发生**覆盖**
5. 扫描变量声明,未被发现的在变量对象中创建一个同名属性并初始化为 undefined,如果已存在,**跳过**
6. 确定上下文中的 this

注:如果 let 以及 const 声明创建阶段会跳过初始化

执行阶段

赋值、寻找函数引用以及解释/执行代码

所以执行上下文类似结构为:

1
2
3
4
5
executionContextObj = {
'scopeChain': { /* 变量对象 + 所有父级执行上下文的变量对象*/ },
'variableObject': { /* 函数参数、 参数,内部变量以及函数声明 */ },
'this': {}
}

变量对象(VO)和活动对象(AO)

当当前上下文执行时,变量对象变成活动对象,所以区别只是同一对象在执行上下文的不同阶段而已

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
funtion foo(i) {
var a = 'hello'
var b = function foo2() {}
function c() {}
}
foo(10)
函数调用的创建阶段:
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: undefined,
b: undefined
},
this: { ... }
}
执行阶段:
fooExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: 'hello',
b: pointer to function privateB()
},
this: { ... }
}

提升

变量以及函数声明的提升,原理就在于解析器创建变量对象的过程,不啰嗦。

结语

知其然,知其所以然,想必是极好的

JavaScript 变量与内存

发表于 2018-12-01 | 分类于 javascript

JavaScript 变量与内存

知其然,知其所以然

变量

根据 ECMA-262 定义,JavaScript 中的变量区别于其他编程语言。JavaScript 中的变量只是用于保存特定值的名称,而变量的值数据类型可在脚本的生命周期改变。
也就是说“变量无类型,有类型的是变量的值”

数据类型

JavaScript 中变量值可能包含两种数据类型:基本类型 和 引用类型。

基本类型

ES5 中有五种基本数据类型:Undefined Null Boolean Number String,ES6 新增 Symbol
基本类型数据都是保存在栈中的简单数据,按值来访问的,可直接操作保存在变量中的实际的值
基本类型的值是不允许更改的,当你修改了变量的值,所做的只是创建了新值并复制到了原先变量值的位置

引用类型

引用类型的值为保存在内存中的对象,区别于其他语言,JavaScript 中不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。而实际上对对象的操作是对对象引用的操作。

动态属性

两种类型定义方式类似:创建变量并为变量赋值,但不同类型值可进行的操作却有不同:
我们可以为引用类型数据添加属性和方法,也可改变和删除属性和方法,而对于基本类型是不可以的

1
2
3
4
5
6
7
var a = {}
a.b = 'test'
a.b //test
var a = 1;
a.test = 'test data'
a.test //undefined

变量复制

除了变量存储方式不同,变量的复制也存在着不同

阅读全文 »

iPhone X 适配

发表于 2018-02-13 | 分类于 移动端

这篇文章迟到了很久,暂且记录一下自己遇到的坑

html5网页

因为目前就职公司采用的H5响应式驱动的主体项目,app 都是基于的 webview 开发,当 iPhone X 上市后,适配促成了新的兼容任务。

新属性

为了更好的适配 iPhone X,iOS 11 新增了几个特性用于处理那诡异的刘海屏。苹果公司还对 iPhone X 的屏幕内容作了安全距离限定,美其名曰为了更好的用户体验,其实就是为了填自己的坑。。

viewport-fit

iOS11 新增特性,为了适应 iPhone X 对现有的 viewport meta 标签的一个扩展,定义网页在可视窗口的布局方式。safari 浏览器中开发模式可勾选支持调试。
属性:

  • contain:可视窗口包含网页内容,即内容会在安全区域显示
  • cover:网页内容覆盖可视窗口
  • auto: 默认值,同contain表现是一致的

详情见文档

constant

iOS11 新增特性,webkit 的 css 函数,用于设定安全区域与边界的距离,有四个预定义变量。

  • safe-area-inset-left:安全区域距离左边边界距离
  • safe-area-inset-right:安全区域距离右边边界距离
  • safe-area-inset-top:安全区域距离顶部边界距离
  • safe-area-inset-bottom:安全区域距离底部边界距离

我们需要关注的就是 safe-area-inset-bottom,对应也就是底部小黑条的处理
同时需要注意的就是,viewport-fit 为 contain 时,constant 函数是不起作用的,需要配合 cover 使用,不支持 constant 的浏览器会被忽略此属性

阅读全文 »

windows 下面那些让人抓狂的东西

发表于 2017-10-08 | 分类于 OS

作为一个混迹windows的程序员,没事重装一下电脑简直和吃饭一样简单,但是每次装完都会被有些东东恶心到。。

系统重装

开机的无效索引

装完系统,如果是u盘安装之类的话,大都会多出一个无效索引,也就是旧系统的索引,不能忍!

  1. Win + R 键入 msconfig,打开系统配置
  2. 点击 “引导” 菜单进行管理,删除无效项即可

window.old文件夹删除

“Windows.old” 文件夹包含升级win10前系统的 “Windows”、“Program Files”、“Users”这三个目录中的文件,将之前的系统文件和安装的程序文件都做了备份。这是微软出于人性化的考虑,让没有来得及备份重要文件的用户可以再次选择备份。
对不起,我不打算考虑!

  1. 系统盘右键 - 属性 - 磁盘清理
  2. 扫描完成 - 清理系统文件 列表中勾选”以前的Windows安装”,确定,待完成退出
    阅读全文 »

从Repaint/Reflow到css选择器

发表于 2017-10-05 | 分类于 html

什么是Repaint/Reflow?

先扒一张图,来解释下浏览器的工作流程

Repaint-Reflow.png

上图可归纳为四步:

  1. 解析构建 DOM 树
    渲染引擎开始解析 html 文档,转换树中的标签或者生成的标签到 DOM 节点,这时的它称为内容树
  2. 构建渲染树
    解析所有 CSS,并据此计算节点样式,创建渲染树
  3. 布局渲染树
    从根节点递归调用,计算元素的大小位置,并把每个节点放在该出现的精准坐标位置
  4. 绘制渲染树
    遍历渲染树,每个节点使用 UI 后端层绘制

从以上不难看出,Repaint 和 Reflow 发生在了第三四步,故给出定义:
浏览器在解析页面时,根据 css 以及 js来计算并把相应的元素置于该出现的位置,这个过程就是 Reflow;
当元素的位置大小颜色确定后,浏览器会按照各自的属性进行绘制,这个过程就是 Repaint。故我们需要避免引发此类操作,
以此来提高渲染速度。

阅读全文 »

BFC(Block Formatting Content)

发表于 2017-09-19 | 分类于 html

What is BFC?

BFC 是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。

当涉及到可视化布局的时候,BFC 为我们提供了一个环境,这个环境规定着其布局的规则,而不同环境之间的布局不会相互影响。
想要更好的理解这个概念,需要先理解 Box 和 Formatting Context 的概念。网页的布局核心就是盒子的组成排列,这些盒子就是 Box。盒子的类型和 display 属性决定着这个 Box 的类型。
不同类型的 Box,会参与不同的 Formatting Context(决定如何渲染文档的格式结构),然后其内元素就会以不同方式渲染。例如:

  • block-level box :display 属性为 block, list-item, table 的元素,会生成 block-level box,
    并参与 block formatting context;
  • inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box,
    并参与 inline formatting context

而 Formatting Context 是一块渲染区域,它决定着其子元素如何定位,以及与其他元素的位置关系。
通过上面一些概念,建议把 BFC 简单理解为一种属性,在具有此属性的容器中,元素按照 BFC 的规则实现布局。比如浮动元素会形成 BFC,这就是为什么我们看到浮动元素布局跟普通文档流的布局有所差别的原因。

阅读全文 »
12
Somnus13

Somnus13

19 日志
8 分类
14 标签
RSS
GitHub Twitter 微博
© 2016 - 2019 Somnus13