1、 使用原生js实现–原型链使用
(10).add(10).reduce(2).add(10) //28
Number.prototype.add = function(num) {
return this + num;
}
Number.prototype.reduce = function(num) {
return this - num;
}
var res = (10).add(10).reduce(2).add(10);
console.log(res);
2、 继承遇到的坑
<script>
function Tree(){
}
Tree.prototype.moreLeafs=function(){
// this.leaf++;
console.log(this);
console.log(this.leaf);
}
Tree.prototype.leaf=2;
var t1 = new Tree();
t1.moreLeafs();
t1.moreLeafs();
var t2 = new Tree();
t2.moreLeafs();
t1.leaf == t2.leaf; //false
t1.moreLeafs == t2.moreLeafs; //true
</script>
答案是:1,2,1。红宝书中有这样一段话:对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该属性会屏蔽原型中的那个属性。
3、函数柯里化
如下代码:
var fn=function(a,b,c){
return a+b+c;
}
需要写一个函数,满足curry(fn)(1)(2)(3) //6
这题很明显,考察函数的柯里化,函数的柯里化还不懂是啥的童鞋可以看这里。
按照题目的要求需要把fn作为第一个参数传进去,而且给出结果刚好是fn运算后给出的结果。
所以我的思路是要有一个函数将fn函数所需参数全部集中到一个数组上,集中完毕后调用fn函数,我的代码如下:
var fn = function(a,b,c) {
return a+b+c;
}
function curry(fn) {
var arr = [],
mySlice = arr.slice
fnLen = fn.length;
function curring() {
arr = arr.concat(mySlice.call(arguments));
if(arr.length < fnLen) {
return curring;
}
return fn.apply(this, arr);
}
return curring
}
curry(fn)(1)(2)(3);//6
bind函数是柯里化的一个用法。
4、记忆缓存
函数可以将先前操作的结果记录在某个对象里,从而避免无谓的重复运算。主要使用 闭包及缓存数组 实现。
方法一采用类似于jQuery缓存的方法,使用对象存储键值对,用闭包封装起来。对于一些有容量限制的可以做超容处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
// 方法一
/* 创建缓存数组 */
function createCache() {
var cache = {}; //对象
return function(key, value) {
if (value !== undefined) { //如果存在值,则为设置key的值为value
cache[key] = value;
return cache[key];
} else { //如果value为undefined,则为获取值
return cache[key];
}
}
}
//以斐波那契为例
var count = 0;
function fib() {
var cache = createCache();
function cacheFib(n) {
if (cache(n) !== undefined) {
return cache(n);
} else {
count++;
if (n <= 2) {
cache(n, 1);
return 1;
}
var temp = cacheFib(n - 1) + cacheFib(n - 2);
cache(n, temp);
return temp;
}
}
return cacheFib;
}
var myfib = new fib();
console.log(myfib(9)); //34
console.log(count); //9
</script>
</body>
</html>
方法一扩展:超容处理的createCache方法:
/* 创建缓存数组-限制缓存大小 */
function createCache() {
var cache = {}; //做缓存对象,以键值对的形式存储
var index = []; //存储键,键有顺序,方便做超容处理
return function(key, value) {
if (value !== undefined) { //如果存在值,则为设置key的值为value
cache[key] = value; //将键值存储在缓存对象中,做缓存
index.push(key); //将键存储在index数组中,和cache对应
if (index.length >= 50){
//如果超出容量,则删除最早进入缓存的数据
var temp = index.shift();
delete cache[temp];
}
return cache[key];
} else { //如果value为undefined,则为获取值
return cache[key];
}
}
}
cache缓存
作用:存储常用数据,提供使用,提升性能
原理:使用对象,以键值对形式存储;使用数组存储键,键有顺序,超出缓存容量,则删除最早进入缓存的一个(即数组第一个);使用闭包封装函数
jQuery的缓存处理:
function createCache() {
var keys = [];
function cache( key, value ) {
// 使用(key + " ") 是为了避免和原生(本地)的原型中的属性冲突
if ( keys.push( key + " " ) > 3 ) {
// 只保留最新存入的数据
delete cache[ keys.shift() ];
}
// 1 给 cache 赋值
// 2 把value返回
return (cache[ key + " " ] = value);
}
return cache;
}
var typeCache = createCache();
typeCache("monitor");
console.log(typeCache["monitor" + " "]); //undefined
typeCache("monitor1","张");
console.log(typeCache["monitor1" + " "]); //张
typeCache("monitor2","刘");
console.log(typeCache["monitor2" + " "]); //刘
typeCache("monitor3","彭");
console.log(typeCache["monitor3 "]); //彭
console.log(typeCache["monitor "]); ////undefined
方法二来自《js语言精粹》,提供了一个简短精悍的memorizer方法,对于不同的需要记忆的函数可以复用,比如斐波那契函数、阶乘函数。
// --------------------------------方法二:记忆函数-精简写法
var count1=0;
var memoizer = function(memo, formula) {
var recur = function(n) {
var result = memo[n];
if (typeof result !== 'number') {
result = formula(recur, n);
memo[n] = result;
}
return result;
};
return recur;
}
//斐波那契函数
var fibonacci = memoizer([0, 1], function(recur, n) {
count1++;
return recur(n - 1) + recur(n - 2);
});
console.log(fibonacci(9)); //34
console.log(count1); //8
//阶乘函数
var factorial = memoizer([1,1],function(recur,n){
return n*recur(n-1);
});
console.log(factorial(5)); //120