js设计模式基础

来源:互联网 发布:pl sql developer官网 编辑:程序博客网 时间:2024/04/29 12:18

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); // ducksayName(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); // 输出:2console.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( [] ); // 输出:trueType.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. getSinglevar 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 32.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);};
原创粉丝点击