ES6: 模块编程
Javascript模块的限制
只能运行于严格模式
模块中的顶级作用域中的变量,不会被自动添加到全局作用域
顶级作用域的this为undefined
导出如果想让模块中的变量、函数、类被其他模块使用,需要将其导出,导出的方法如下:
export var color = “red”;
export function print_hello(){};
export { print_hello }
export { print_hello as printh };
export default function print_hello(){};
export default print_hello
export { print_hello as default}
导入如果想使用其他模块中的变量、函数、类,需要将其导入。导入后的变量、类、函数为只读。导入的方法如下:
import { color, print_hello } from “./example.js”;
import * as example from “./example. ...
ES6:数组
新增的静态方法Array.of() :可以将传入的参数逐个传入数组,即使只有一个数值类型的参数,也会成为新数组的成员,而不是代表数组的长度 Array.from():可以将类数组结构转化为数组,例如: Array.from(arguments). 利用Array.from()也可以转换原来的数组,例如:
let trans_args = function() {
let args = Array.from(arguments, (value)=>value + 1);
console.log(args);
}
trans_args(1, 2, 3);
$ node test.js
[ 2, 3, 4 ]
新增的普通方法find() 与findIndex():传入一个回调函数来表明查找的条件,例如:
> let arr = [1, 2, 3, 4, 5];
undefined
> arr.find((n)=>n>3);
4
> arr.findIndex((n)=>n>3);
3
fill(va ...
ES6中的类
ES6中添加的class关键字其实并非真正的类,而是ES5用函数来模拟类的语法糖。在ES6中可以用如下的语法创建一个类:
class Students {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(this.name);
}
sayAge() {
console.log(this.age);
}
}
let st1 = new Students('sen', 18);
st1.sayName();
st1.sayAge();
使用ES6的class语法糖和ES5自定义的类还是有些区别的:
类的声明不会被提升,类的实例化只能在类的声明之后
类声明中的代码只能运行在严格模式下
类中的方法是不可枚举的
实例化的时候必须加new关键字
在 ...
ES6: 迭代器与生成器
什么是迭代器?迭代器是一个对象,它拥有一个next方法,调用next方法会返回一个对象,该对象有两个属性值,value和done。每次调用next方法,返回的value表示可迭代对象中的下一个值,done表示迭代是否完成。根据此定义,可用下面的代码实现一个迭代器:
let create_iter = function(items) {
let i = 0;
return {
next: function() {
let value, done;
if (i >= items.length) {
value = null;
done = true;
} else {
value = items\[i++\];
done = false;
}
...
单链表反转
实现单链表反转的思路实现单链表反转的难点在于,如果让当前节点的next指向前驱节点,那么链表就断了,所以解决的办法就是在进行反转操作之前用一个临时指针变量保存后继节点的地址。
单链表反转的代码实现#include <stdio.h>
#include <stdlib.h>
typedef struct LIST_NODE {
int data;
struct LIST_NODE* next;
} LIST_NODE;
void show\_list(LIST\_NODE *head) {
LIST_NODE *p = head->next;
while(p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\\n");
}
void reverse\_list(LIST\_NODE *head) ...
冒泡排序、插入法排序及选择排序
冒泡排序、插入法排序以及选择排序是排序算法中比较基础的三种,其平均时间复杂度都是O(n^2)。
原理介绍冒泡排序冒泡排序的步骤是:比较相邻两个数,看是否满足大小关系,如果不满足则交换这两个数,使他们满足大小关系,这样可以保证最大(最小)的数始终会向后流动,循环一次之后,最大(最小)的数就会被交换到数组的最后。一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
插入法排序插入法排序的思路是:把数组分成两个部分:排好序的,和未排序的。开始的时候,数组的第一个元素会被当做拍好序的部分,对其余未排好序的数值进行迭代,将其插入到排好序的部分中合适的位置。
选择法排序选择法排序和插入法排序类似,都是将数组分为排好序的和未排序的两个部分。不同的是,选择法排序每次迭代都会选择未排序部分中的最小(最大)值,将其插入到排好序部分的队首(队尾)。
C语言实现需要实现四个函数, 第一个是打印数组,接下来三个函数分别实现三种排序算法:
void print_arry(int *a, int len)
static inline void insertion_ ...
用单链表实现LRU缓存置换算法
缓存置换算法所解决的问题在存储系统的金字塔结构中,缓存的存取速度比内存快,然而成本比内存高,所以缓存的容量有限。缓存置换算法所要解决的问题便是在容量有限的缓存中,存放哪些数据可以提升缓存命中率。
LRU缓存置换算法的核心思想LRU算法认为最近访问过的数据被再次访问的可能性最大,所以缓存中存放的是最近使用过的数据。具体的做法是:
把缓存当做一个队列,队首的数据是最近被访问的数据,而队尾的数据则是即将被置换出缓存的数据。
每当有新数据被访问时,会在队列中查找该数据,如果存在,就被该数据挪到队首。
如果被访问的数据没有在队列(缓存)中,而且缓存未满,则该数据被放到队首。
如果被访问的数据没有在队列中,然而缓存已经满了,则把队尾的数据从队列中删除,再把新数据放置到队首。
用C语言实现LRU缓存置换算法#include <stdio.h>
#include <stdlib.h>
#define CACHE_SIZE 20
int nr_of_list = 0;
typedef struct CACHE_ITEM {
in ...
ES6: Set 与 Map
Set
let my_set = new Set();
let my_set = new Set([1, 1, 2, 2]);
my_set.add(5);
my_set.delete(5);
my_set.has(5);
my_set.forEach(function(value){});
let my_set = WeakSet() // 只允许对象作为set的元素,便于垃圾回收
Map
let my_map = new Map();
let map = new Map([[“name”, “Nicholas”], [“age”, 25]]);
my_map.set(key, value);
my_map.get(key)
my_map.has(key)
my_map.delete(key);
my_map.clear();
my_map.size;
my_map.forEach(function(value, key, ownerMap) { console.log(key + “ “ + value); co ...
ES6: 符号类型
引入原因:
实现私有属性 let s = Symbol() let obj = {[s]: ‘hello world’}; console.log(obj.s); //undefined
符号值唯一 let s = Symbol() let m = Symbol() console.log(s === m)
创建:
不能用字面量形式创建
使用Symbol(desc)函数创建,不需要添加new
Symbol.for(key)在全局符号注册表中查找key符号值,如果找到就返回,没找到就创建一个新的符号值
Symbol.keyFor(symbol): 返回符号值的key
枚举:
符号类型的key是不能被枚举的,Object.keys()以及Object.getOwnPropertyNames()都不能返回符号类型的key
Object.getOwnPropertySymbols()则会返回对象中所有符号类型的key
共享符号值:
Symbol.for(desc): 在全局符号注册表中查找描述为desc的符号,如果找到,返回这个符号值,如果 ...
ES6: 对象和数组解构
所谓解构,指的是将数据结构分解为更小的部分,从而使数据提取变得容易。 对象解构:
使用解构时,必须提供初始化值 let Person = { name: 'sen', age: 18 } let {name, age} = Person;
解构表达式的值为=右侧的值
如果对象中没有同名属性时,解构表达式新赋值的变量的值为undefined
解构对象只是赋值时,需要加()
赋值给不同名的变量 let Person = { name: 'sen', age: 18 } let {name: localName, age: localAge} = Person;
设置默认值 let Person = { name: 'sen', age: 18 } let {name, age: localAge = 18} = Person;
嵌套解构 let Person = { name: ...