JS 常用方法的源码实现
字符串简单模板引擎
1
2
3
4
5
6
|
let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
name: '姓名',
age: 18
}
render(template, data); // 我是姓名,年龄18,性别undefined
|
1
2
3
4
5
6
7
8
9
|
function render(template, data) {
const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
if (reg.test(template)) { // 判断模板里是否有模板字符串
const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
return render(template, data); // 递归的渲染并返回渲染后的结构
}
return template; // 如果模板没有模板字符串直接返回
}
|
千分位分隔符
1
2
3
4
5
6
7
|
parseMoney(1234.56); // 1,234.56
function parseMoney(num) {
const [integer, decimal] = String.prototype.split.call(num, '.');
integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,');
return integer + '.' + (decimal ? decimal : '');
}
|
实现防抖函数
防抖函数原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
1
2
3
4
5
6
7
8
9
|
const debounce = (fn, delay) => {
let timer = null;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
|
实现节流函数
节流函数原理:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
1
2
3
4
5
6
7
8
9
10
11
|
const throttle = (fn, delay = 500) => {
let flag = true;
return (...args) => {
if (!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay);
};
};
|
instanceOf
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 模拟 instanceof
function instance_of(L, R) {
//L 表示左表达式,R 表示右表达式
var O = R.prototype; // 取 R 的显示原型
L = L.__proto__; // 取 L 的隐式原型
while (true) {
if (L === null) return false;
if (O === L)
// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
|
模拟new
new操作符做了这些事:
- 它创建了一个全新的对象
- 它会被执行[[Prototype]](也就是__proto__)链接
- 它使this指向新创建的对象
- 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上
- 如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用将返回该对象引用
1
2
3
4
5
6
7
8
9
10
|
function objectFactory() {
const obj = new Object();
const Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
const ret = Constructor.apply(obj, arguments);
return typeof ret === "object" ? ret : obj;
}
|
实现 new
1
2
3
4
5
6
7
8
9
|
function New(f) {
return function () {
var o = {
"__proto__": f.prototype
};
f.apply(o, arguments);
return o;
}
}
|
实现一个call
1
2
3
4
5
6
7
|
Function.prototype.myCall = function(context, ...args) {
context.fn = this;
context.fn(...args);
let result = context.fn(...args);
delete context.fn;
return result;
};
|
实现apply
1
2
3
4
5
6
7
8
9
10
11
|
Function.prototype.myApply = function(context, arr) {
context.fn = this;
let result;
if (!arr) {
result = context.fn();
} else {
result = context.fn(...arr);
}
delete context.fn;
return result;
}
|
实现bind
1
2
3
4
5
6
7
8
9
10
|
Function.prototype.es6Bind = function(context, ...rest) {
if (typeof this !== 'function') throw new TypeError('invalid invoked!');
var self = this;
return function F(...args) {
if (this instanceof F) {
return new self(...rest, ...args)
}
return self.apply(context, rest.concat(args))
}
}
|