您的位置:首页 > Web前端 > JavaScript

js设计模式基础

2017-10-22 14:59 288 查看

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.call
Function.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: fun
d5ef
ction(){
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);
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: