js设计模式基础

1. 多态

多态的实际含义是:同一操作作用于不同的对象上面,可以产生不同的解释和不同的结果。

var sayName = function( obj ){
    obj.prototype.sayname.call(obj);
}
var Animal = function(){};
Animal.prototype.sayname = function(){
    console.log( this.name );
}
var duck = {
    name:"duck"
}
duck.prototype = new Animal;
var chick = {
    name:"chick"
}
chick.prototype = new Animal;
sayName(duck); // duck
sayName(chick);//chick

上面的例子很清楚的说明了 多态 和继承 以及原型模式,这只是一个很简单的例子

2.call this apply

1.this 使用方法 对象方法调用 普通函数调用 构造器调用
Function.prototpe.callFunction.prototype.apply调用(this指向,类数组的参数)若第一个为null则默认为宿主对象

 var obj = {
       a: 1,
       getA: function(){
                console.log( this === obj );
                console.log( this.a );
       }
 };
 obj.getA();
 this.name = 'pi';
 var obj = {
    name: 'seven',
    getname: function(){
        return this.name;
    }
 };
 var getName = obj.getname;
 console.log( getName() );
 var MyClass = function(){
 this.name = 'sven';
 return 'pipi'
 };
 var obj = new MyClass();
 console.log ( obj.name ); // 输出:anne
  var obj1 = {
 name: 'sven',
 getName: function(){
 return this.name;
 }
 };
var obj2 = {
name: 'anne'
 };
 console.log( obj1.getName() ); // 输出: sven
  console.log( obj1.getName.call( obj2 ) ); // 输出:anne
 var obj = {
myName: 'sven',
getName: function(){
 return this.myName;
 }
 };
 console.log( obj.getName() ); // 输出:'sven'
 var getName2 = obj.getName; //普通函数 this指向全局
 console.log( getName2() ); // 输出:undefined //丢失的this

2.call和apply用途(区别,call是一个个传参数而 apply是数组传参)
1.改变this的指向
2.bind指定函数内部this的指向

 Function.prototype.bind = function() {
    var self = this, // 保存原函数
        context = [].shift.call(arguments), // 需要绑定的 this 上下文
        args = [].slice.call(arguments); // 剩余的参数转成数组
    return function() { // 返回一个新的函数
        return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
        // 执行新的函数的时候,会把之前传入的 context 当作新函数体内的 this
        // 并且组合两次分别传入的参数,作为新函数的参数
    }
};
var obj = {
    name: 'sven'
};
var func = function(a, b, c, d) {
    console.log(this.name); // 输出:sven
    console.log([a, b, c, d]) // 输出:[ 1, 2, 3, 4 ]
}.bind(obj, 1, 2);
func(3, 4);
var A = function(name) {
    this.name = name;
};
var B = function() {
    A.apply(this, arguments);
};
B.prototype.getName = function() {
    return this.name;
};
var b = new B('sven');
console.log(b.getName()); // 输出: 'sven'
(function() {
    Array.prototype.push.call(arguments, 3);
    console.log(arguments); // 输出[1,2,3]
})(1, 2);
var a = {};
Array.prototype.push.call(a, 'first');
Array.prototype.push.call(a, 'two');
console.log(a.length); // 输出:2
console.log(a[0], a[1]); // first two
//要求 1对象本身能够存取属性(number就不行) 2对象的lentgth属性可读写(函数不行)
var func = function(){};
Array.prototype.push.call( func, 'first' );
console.log ( func.length );

3.闭包和高阶函数

var Type = {};
for ( var i = 0, type; type = [ 'String', 'Array', 'Number' ][ i++ ];){
(function( type ){
Type[ 'is' + type ] = function( obj ){
return Object.prototype.toString.call( obj ) === '[object '+ type +']';
}
})( type )
};
Type.isArray( [] ); // 输出:true
Type.isString( "str" ); // 输出:true

闭包用法
1.封装变量

 var mult = (function() {
    var cache = {};
    var calculate = function() { // 封闭 calculate 函数
        var a = 1;
        for (var i = 0, l = arguments.length; i < l; i++) {
            a = a * arguments[i];
        }
        return a;
    };
    return function() {   
        var args = Array.prototype.join.call(arguments, ',');
        if (args in cache) {
            return cache[args]; //保存的参数 若运算过 直接输出 否则运算
        }
        return cache[args] = calculate.apply(null, arguments);
    }
})();

2.高阶函数

// 1.callback 回调函数
// 2.Array.prototype.sort
// 3. 判断数据的类型(返回值)
var isType = function(type) {
    return function(obj) {
        return Object.prototype.toString.call(obj) === '[object ' + type + ']';
    }
};
4. getSingle
var getSingle = function(fn) {
    var ret;
    return function() {             //单例模式简单实现
        return ret || (ret = fn.apply(this, arguments));
    };
};
// 高阶函数实现AOP
// AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些
// 跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后,
// 再通过“动态织入”的方式掺入业务逻辑模块中。这样做的好处首先是可以保持业务逻辑模块的
// 纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块。
Function.prototype.before = function(beforefn) {
    var __self = this; // 保存原函数的引用
    return function() { // 返回包含了原函数和新函数的"代理"函数
        beforefn.apply(this, arguments); // 执行新函数,修正 this
        return __self.apply(this, arguments); // 执行原函数
    }
};
Function.prototype.after = function(afterfn) {
    var __self = this;
    return function() {
        var ret = __self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
    }
};
var func = function() {
    console.log(2);
};
func = func.before(function() {
    console.log(1);
}).after(function() {
    console.log(3);
});
func(); //1 2 3
2.currying 柯里化 将一部分参数放入函数后返回另一个函数 直到需要时 一次性调用
var cost = (function(){
    var args = [];
    return function(){
        if ( arguments.length === 0 ){
            var money = 0;
            for ( var i = 0, l = args.length; i < l; i++ ){
                money += args[ i ];
            }
            return money;
        }else{
            [].push.apply( args, arguments );
        }
    }
})();
cost( 100 ); // 未真正求值
cost( 200 ); // 未真正求值
cost( 300 ); // 未真正求值
console.log( cost() ); // 求值并输出:600
//3.函数节流
var throttle = function(fn, interval) {
    var __self = fn, // 保存需要被延迟执行的函数引用
        timer, // 定时器
        firstTime = true; // 是否是第一次调用
    return function() {
        var args = arguments,
            __me = this;
        if (firstTime) { // 如果是第一次调用,不需延迟执行
            __self.apply(__me, args);
            return firstTime = false;
        }
        if (timer) { // 如果定时器还在,说明前一次延迟执行还没有完成
            return false;
        }
        timer = setTimeout(function() { // 延迟一段时间执行
            clearTimeout(timer);
            timer = null;
            __self.apply(__me, args);
        }, interval || 500);
    };
};
//4. 分时函数 数据 函数 数量
var timeChunk = function( ary, fn, count ){
    var obj,
    t;
    var len = ary.length;
    var start = function(){
        for ( var i = 0; i < Math.min( count || 1, ary.length ); i++ ){
            var obj = ary.shift();
            fn( obj );
        }
    };
    return function(){
        t = setInterval(function(){
           if ( ary.length === 0 ){ // 如果全部节点都已经被创建好
            return clearInterval( t );
           }
           start();
        }, 200 ); // 分批执行的时间间隔,也可以用参数的形式传入
    };
};
//4.惰性加载函数
var addEvent = function(elem, type, handler) {
    if (window.addEventListener) {
        addEvent = function(elem, type, handler) {
            elem.addEventListener(type, handler, false);
        }
    } else if (window.attachEvent) {
        addEvent = function(elem, type, handler) {
            elem.attachEvent('on' + type, handler);
        }
    }
    addEvent(elem, type, handler);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值