Dong's Blog

路漫漫其修远兮,吾将上下而求索


  • 首页

  • 归档

  • 标签

【vue源码】简单实现directive功能

发表于 2018-01-04 | 分类于 vue

2018年首个计划是学习vue源码,查阅了一番资料之后,决定从第一个commit开始看起,这将是一场持久战!本篇介绍directive的简单实现,主要学习其实现的思路及代码的设计(directive和filter扩展起来非常方便,符合设计模式中的开闭原则)。

阅读全文 »

作用域是什么

发表于 2017-11-16 | 分类于 你不知道的Js

作用域是什么

编译原理

传统编译语言的流程中,程序中的一段代码在执行之前会经历三个步骤,统称为“编译”。

  1. 分词/词法分析
    将字符组成的字符串分解成有意义的代码块。
  2. 解析/语法分析
    这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树,这个树被称为“抽象语法树(Abstract Syntax Tree,AST)”。
  3. 代码生成
    将AST转换为可执行的代码,这个过程与语言和目标平台息息相关。

JavaScript引擎不会有大量时间用来进行优化,因为它的编译过程不是发生在构建之前的,而是发生在代码执行前的几微妙(甚至更短)的时间内。

简单地说,任何JavaScript代码片段在执行前都进行编译(通常就在执行前)。

理解作用域

编程语言最基本功能就是可以存储变量当中的值,后续还可以继续访问或进行修改。语言需要设计一套规则来存储变量,方便查找这些变量,这套规则就成为作用域。

变量的赋值操作会执行两个动作,首先编译器会在当前作用域中生成一个变量(如果之前没有生成过),然后在运行时引擎会在作用域中查找该变量,如果能找到就会对它赋值,否则会抛出一个异常!

LHS和RHS查询

LHS是查找变量容器本身,RHS是要得到变量的值。下面看一个例子:

1
2
3
4
function foo(a){
console.log(a);
}
foo(2);
  1. foo函数调用需要对foo进行RHS查询,引擎会问作用域是否有foo。
  2. 2赋值给foo形参a之前,需要对a进行LHS查询。
  3. console对象进行的是RHS查询,并且检查是否有一个叫log的方法。
  4. 最后对a进行RHS查询得到2,程序输出。

作用域嵌套

当一个块或函数嵌套在另一个块或函数中时,就发生了作用域嵌套。因此,在当前作用域中无法找到某个变量时,引擎会在外层嵌套的作用与众继续查找,知道找到该变量,或抵达最外层的作用域为止。

异常

为什么区分LHS和RHS是一件重要的事情?

因为在变量还没有声明的情况下,这两种查询的行为是不一样的。考虑如下代码:

1
2
3
4
5
function foo(a){
console.log(a + b);
b = a;
}
foo(2);

第一次对b进行RHS查询时是无法找到该变量的。也就是说,这是一个“未声明”的变量。

如果RHS查询在所有嵌套的作用域中都找不到所需的变量,引擎会抛出ReferenceError异常。

而当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域会创建一个具有该名称的变量,并将其返还给引擎(非严格模式下)。

严格模式下LHS对找不到变量的处理方式和RHS一样,都会抛出ReferenceError异常。

ReferenceError同作用域判别失败相关,TypeError是作用域判别成功了,但是对结果的操作是非法不合理的,如引用null或undefined中的属性值。

ES6中模板字符串详解

发表于 2017-08-24 | 分类于 ES6

模板字符串基础用法很简单,常用于变量内插。但它能和类似Handlebars这样的模板引擎相媲美…一起来看一下吧~

基础语法

具体可以参考之前写的一篇文章《深入理解ES6-块级作用域和字符串》

使用模板字符串实现模板引擎功能

先使用Handlebars来实现一个常见例子,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var Handlebars = require('handlebars');
// 工具方法
Handlebars.registerHelper('capitalize', function (str) {
return str[0].toUpperCase() + str.slice(1);
});
// 编译模板
var page = Handlebars.compile(`
<h2>People</h2>
<ul>
{{#each people}}
<li>
<span>{{capitalize name}}</span>
{{#if ../isAdmin}}
<button>Delete </button>
{{/if}}
</li>
{{/each}}
</ul>
`);
// 渲染
page({isAdmin: true, people: [{name: 'lisi'}, {name: 'zhangsan'}]});

下面使用模板字符串来实现该功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function capitalize(string) {
return string[0].toUpperCase() + string.slice(1);
}
var p = ({people, isAdmin}) => `
<h2>People</h2>
<ul>
${people.map(person => `
<li>
<span>${capitalize(person.name)}</span>
${isAdmin ? `<button>Delete </button>` : ''}
</li>
`).join('')}
</ul>
`;
p({isAdmin: true, people: [{name: 'lisi'}, {name: 'zhangsan'}]});

怎么样,是不是很简洁!还没完事呢,下满我们再继续优化这段代码。

给模板字符串增加辅助方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var helpers = {
if(condition, thenTpl, elseTpl = '') {
return condition ? thenTpl : elseTpl;
},
registerHelper(name, fn) {
helpers[name] = fn;
}
};
helpers.registerHelper('capitalize', (string) => {
return string[0].toUpperCase() + string.slice(1);
});
var p = ({people, isAdmin}) => `
<h2>People</h2>
<ul>
${people.map(person => `
<li>
<span>${helpers.capitalize(person.name)}</span>
${helpers.if(isAdmin, `<button>Delete </button>`)}
</li>
`).join('')}
</ul>
`;

这里只演示了将三元表达式逻辑抽离到helper中if函数,还可以自定义helper函数,这样可以把复杂的业务逻辑抽离出来,让模板字符串尽量保持简洁。

使用JavaScript实现快速排序

发表于 2017-08-20 | 分类于 algorithm

概念

  • 在数据集之中,选择一个元素作为”基准”(pivot),可以随机选择。这里我们选择最后一位。
  • 将小于基准的元素移到基准的左边,大于基准的元素移到基准的右边。
  • 对基准左边和右边不断重复上面两步,直到所有子集只剩下一个元素为止。
阅读全文 »

使用JavaScript实现归并排序

发表于 2017-08-18 | 分类于 algorithm

在计算机科学领域里,归并排序是一种非常有用的排序算法。它的时间复杂度为O(n log n),使得它非常高效。另外它也是一种稳定排序(类似插入排序)。正是因为这些优点,火狐和Safari浏览器中Array.prototype.sort()底层排序算法就使用的归并排序。

阅读全文 »

使用JavaScript实现冒泡排序

发表于 2017-08-17 | 分类于 algorithm

概念

在冒泡排序中,是从数组中第一个元素开始并且依次相邻元素之间进行比较。如果第一个元素大于第二个元素,则交换它们的位置。否则第二个与第三个元素进行比较,以此类推。在第一轮循环结束后,会将最大的元素放到数组的末尾。

阅读全文 »

使用JavaScript实现选择排序

发表于 2017-08-17 | 分类于 algorithm

概念

在选择排序中,我们先假设数组中第一个元素最小,然后从下个元素开始寻找比该元素小的其它元素,如果找到,则在一次循环结束后交换这两个元素的位置。这之后位于数组中第一个位置中的元素就是最小的了,也就是1位置前的元素是有序的了。

接着我们假设第二个元素在该数组剩余元素中是最小的,依次遍历其它元素从中找出最小元素,并在循环结束后交换位置。这之后第一个和第二个元素已经排好顺序了。按照同样的方式来处理其它剩余元素,之后就得到一个有序的数组。

阅读全文 »

使用JavaScript实现插入排序

发表于 2017-08-17 | 分类于 algorithm

概念

在插入排序中,我们将初始无序的数组分为两部分,有序部分和无序部分。有序部分初始化时只有一个元素(一般为数组第一个元素)。之后我们将无序部分中的元素一个个地插入到有序部分,每次插入的时候会寻找合适的位置并扩展有序部分。

阅读全文 »

学习dashboard中网格拖拽效果的实现

发表于 2017-08-05

本文对田老师写的flowgrid插件做详细的讲解,为此特地写了一个小项目,暂且就叫vue-dragrid,预览效果点击这里,下面会针对一个个commit来进行讲解,所有commit请看这里。

阅读全文 »

Js中的数值类型转化规则

发表于 2017-08-03

有3个函数可以把非数值转化为数值:Number()、parseInt()、parseFloat()。其中Number()可以用于任何数据类型,而另两个函数则专门用于把字符串转成数值。这三个函数对同样的输入会有返回不同的结果。

阅读全文 »
123
Dong

Dong

26 日志
7 分类
8 标签
© 2018 Dong
由 Hexo 强力驱动
主题 - NexT.Muse