【js语言精粹】第四章 函数

在JavaScript中一共有四种调用模式:方法调用模式、函数调用模式、构造器调用模式和apply调用模式。这些模式在如何初始化关键参数this上存在差异。

1. 方法调用模式

当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如:

var myObject = {
    value:0;
    increment:function(inc){
        this.value += typeof inc === 'number' ? inc : 1;
    }
};
myObject.increment(2)
document.writeln(myObject.value); // 3

方法可以使用this去访问对象,所以它能从对象中取值或修改该对象。this 到对象的绑定发生在调用的时候,“迟绑定”

2. 函数调用模式

当一个函数并非一个对象的属性时,那么它被当作一个函数来调用:

var sum = add(3,4);  // sum 的值为7

当函数以此模式调用时,this被绑定到全局对象。这是语言设计上的一个错误。解决的方法是定义一个变量并给它赋值为this。

myObject.double = function(){
    var that = this;
    this.value = 6;
    var helper = function(){
        console.log(that.value);
    }
    helper();
}
myObject.double(); // 6

3. 构造器调用模式

如果在一个函数前面带上new来调用,那么将创建一个隐藏连接到该函数的prototye成员的新对象,同时this将会被绑定到那个新对象上。

new 前缀也会改变return语句的行为。?

var Quo = function(string){
    this.status = string;
}
Quo.prototype.get_status = function(){
    return this.status;
}
var myQuo = new Quo("confused");
console.log(myQuo.get_status()); // confused

4. Apply调用模式

因为JavaScript是一门函数式的面向对象编程语言,所以函数可以拥有方法。

apply方法接收两个参数。第一个是将被绑定给this的值。第二个就是一个参数数组。

var Quo = function(string){
    this.status = string;
}
Quo.prototype.get_status = function(){
    return this.status;
}
var myQuo = new Quo("confused");

// 自己乱写的add方法
function add(){
    var sum = 0;
    Array.prototype.forEach.call(arguments,function(value,key,array){
            sum+=value;
        });
    return sum;
}
var array = [3,4,5];
var sum = add.apply(null,array); // sum值为7
console.log(sum);

var statusObject = {
    status:'A-OK'
}
var status = Quo.prototype.get_status.apply(statusObject);
console.log(status); // A-OK

 注:new 前缀也会改变return语句的行为。

如果函数以在前面加上new前缀的方式来调用,且返回值不是一个对象,则返回this(该新对象)。返回值是对象是则返回该对象!!!!!

 

1.给类型增加方法

通过Function.prototype增加方法来使得该方法对所有函数可用

Function.prototype.method = function(name,func){
    this.prototype[name] = func;
    return this;
}

给Number.prototype添加一个integer方法来根据数字的正负来判断使用Math.ceiling还是Math.floor

Number.method('integer',function(){
    return Math[this < 0 ? 'ceiling' : 'floor'](this);
});

给String.prototype添加trim方法来移除字符串的末端空格

String.method('trim',function(){
    return this.replace(/\s+|\s+$/g,'');
});
console.log('"'+" n ear ".trim()+''); // n ear

 记忆

函数可以用对象去记住先前的操作,从而能避免无谓的运算。

var memoizer = function(memo,fundamental){
    var shell = function(n){
        var result = memo[n];
        if(typeof result !== 'number'){
            result = fundamental(shell,n)
            memo[n] = result;
        }
        return result;
    };
    return shell;
}
var fib = memoizer([0,1],function(shell,n){
    return shell(n-1)+shell(n-2);
});
var res = fib(30);console.log(res);

套用 柯里化

Function.prototype.method = function(name,func){
    this.prototype[name] = func;
    return this;
}
function add(){
    var sum = 0;
    console.log(arguments);
    Array.prototype.forEach.call(arguments,function(value,key,array){
            sum+=value;
        });
    return sum;
}
Function.method('curry',function(){
    var slice = Array.prototype.slice,
        args = slice.apply(arguments),
        that = this;
    return function(){
        return that.apply(null,args.concat(slice.apply(arguments))); // 如果是调用非内置的方法(slice,forEach..)时一定要传个对象
    }
});
var res = add.curry(1)(2,3,4);
console.log(res); // 10

 

posted @ 2018-03-22 20:59  vxee  阅读(153)  评论(0编辑  收藏  举报