腊月的季节

JavaScript基本知识点

关于js的splice、slice

slice(startIndex, endIndex)不改变原数组,取[startIndex, endIndex)之间的数据,返回数组.
splice(startIndex, delNum, …[])改变原数组,从startIndex开始删除,删除delNum个,并加入若干元素

1
2
3
4
let a = [1, 2, 3];
console.log(a.slice(0, 2)); // [1, 2]
console.log(a.splice(0, 1, 4)) // [1];
console.log(a); // [4, 2, 3]

关于js的bind

js的bind方法,每次都会返回一个新的方法地址,所以在需要记录方法地址时,需要用变量记录。如监听事件,

1
2
3
4
5
6
7
private funcHandle: Function;
private func(){}
window.addEventListener('keydown', this.func.bind(this));
window.removeEventListener('keydown', this.func); // 这种做法是错误的

window.addEventListener('keydown', this.funcHandle = this.func.bind(this));
window.removeEventListener('keydown', this.funcHandle); // 正确做法

关于js的Promise

使用了设计模式中的观察者模式
极简promise雏形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Promise(fn) {
var value = null;
var callbacks = [];

this.then = function(onFulfilled) {
callbacks.push(onFulfilled);
};

function resolve(value) {
callbacks.forEach(function(callback) {
callback(value);
});
};

fn(resolve);
}

可以看的出来当使用者调用then方法时是往这个堆中的callbacks压入方法,Promise内部向外部丢了resolve方法,当外部执行resolve时会依次执行压入的方法,并将参数传递给方法。

这样会带来一个问题,当resolve执行后,注册过的函数都会执行,而后面再进行then的方法不会执行,这显然不是最好的。

于是加入了状态,pending,fulfilled,rejected.
图片加载中

改进后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function Promise(fn) {
var state = 'pending',
value = null,
callbacks = [];
this.then = function (onFulfilled) {
if (state === 'pending') {
callbacks.push(onFulfilled);
return this;
}
onFulfilled(value);
return this;
};
function resolve(newValue) {
value = newValue;
state = 'fulfilled';
setTimeout(function () {
callbacks.forEach(function (callback) {
callback(value);
});
}, 0);
}
fn(resolve);
}

上述代码的思路是这样的:resolve执行时,会将状态设置为fulfilled,在此之后调用then添加的新回调,都会立即执行。

链式Promise
如果用户再then函数里面注册的仍然是一个Promise.

1
2
3
4
5
6
7
8
9
10
11
12
getUserId()
.then(getUserJobById)
.then(function (job) {
// 对job的处理
});
function getUserJobById(id) {
return new Promise(function (resolve) {
http.get(baseUrl + id, function(job) {
resolve(job);
});
});
}

改造方法

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
function Promise(fn) {
var state = 'pending',
value = null,
callbacks = [];
this.then = function (onFulfilled) {
return new Promise(function (resolve) {
handle({
onFulfilled: onFulfilled || null,
resolve: resolve
});
});
};
function handle(callback) {
if (state === 'pending') {
callbacks.push(callback);
return;
}
//如果then中没有传递任何东西
if(!callback.onFulfilled) {
callback.resolve(value);
return;
}
var ret = callback.onFulfilled(value);
callback.resolve(ret);
}
function resolve(newValue) {
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
then.call(newValue, resolve);
return;
}
}
state = 'fulfilled';
value = newValue;
setTimeout(function () {
callbacks.forEach(function (callback) {
handle(callback);
});
}, 0);
}
fn(resolve);
}

关于浏览器的history

一个页面中的历史记录长度: history.length
向历史记录中push一个url: history.pushState() 不改变页面
替换当前路由中的状态: history.replaceState() 不改变页面
回退历史记录: history.back() 改变页面至当前的url
前进历史记录: history.forward() 改变页面当前的url

热评文章