JS函数(一)

函数

JS对象与函数关系更近,与Java类与方法分明有所不同,JS中的函数也就是对象。

函数也可以被定义在其他函数中,一个内部函数除了可以访问自己的参数和变量,也可以访问把它嵌套在其中的父函数的参数和变量。通过函数字面量创建的函数对象包含一个连接到外部上下文的连接。这被称作闭包。

调用

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数还接受两个附加参数:thisarguments

参数this在面向对象编程中非常重要,他的只取决于调用的模式。在JS中一共有4种调用模式:方法调用模式、函数调用模式、构造器调用模式、apply调用模式。这些模式在如何初始化关键参数this上存在差异。

方法调用模式

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

var myObject = {    
    value: 0,
    increnment: function(){
        this.value += 1;
    }
}
myObject.increnment();
console.log(myObject.value);        //=>1   

上述例子中this.value就相当于myObject.value。

函数调用模式

当一个函数直接被调用时就是函数调用模式,this指向全局对象window。

var value = 1;
function increnment(){
    this.value += 1;
}

var myObject = { 
    value: 0,
    callIncrement: function(){
        increnment();
    }
}
myObject.callIncrement();
console.log(value);                 //=>2
console.log(myObject.value);        //=>0

当执行到increment方法时,因为this指向的是全局value,不是myObject.value,所以结果是window.value值发生了改变,而myObject.value不变。

使用that来解决这个问题:

var value = 1;
function increnment(obj){
    obj.value += 1;
}

var myObject = { 
    value: 0,
    callIncrement: function(){
         var that = this;
        increnment(that);
    }
}
myObject.callIncrement();
console.log(value);                 //=>1
console.log(myObject.value);        //=>1

构造器调用模式

通过new关键字调用的函数,属于构造器调用模式,这时this指向这个新对象。

var o = {
    value : 0,
    ConstructorFunction: function(value){
        this.value = value;
        return this.value;
    }
}
var b = new o.ConstructorFunction(2);
console.log(o.value);           //=>0
console.log(b.value);           //=>2

这个对于学习过Java面向对象,其实还是很熟悉的。可以理解为o是一个类,而new出来的是对象,this指向对象。

Apply调用模式

apply(obj,arguments)

obj是对象,arguments是数组。

举例:

var obj = {
    value: 0,
    add: function(value){
        this.value += value;
    }
}
var myObj = {   value: 1    };

obj.add.apply(myObj,[3]);
console.log(obj.value);         //=>0
console.log(myObj.value);       //=>4

这里apply方法第一个参数为this指向对象,第二个参数为调用函数的参数(通过数组方式传递)。因为apply方法使this指向了myObj,所以this.value+=value相当于myObject.value+=value。

arguments数组

函数被调用时,会被默认传入arguments参数。函数可以通过访问它来访问参数列表。有了这个参数,多态在JS中就好像不那么需要了,我们可以直接使用arguments来实现多态。

举例:

function myConcat(separator) {
  var args = Array.prototype.slice.call(arguments, 1);//slice() 方法可从已有的数组中返回选定的元素。
  return args.join(separator);//join() 方法用于把数组中的所有元素放入一个字符串。
}}

// returns "red, orange, blue"
myConcat(", ", "red", "orange", "blue");

// returns "sage. basil. oregano. pepper. parsley"
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

异常

var add = function(a,b){
  if(typeof a !=='number' || typeof b !== 'number'){
    throw{
      name:'TypeError',
      'message':'add needs number'
    }
  }
  return a+b;
}

使用:

try{
  add(1,'two');
}catch(e){
  alert(e.name+":"+e.message);//TypeError:add needs number
}

扩充类型的功能

Function基本对象

Function 构造器会创建一个新的 Function 对象。 在 JavaScript 中每个函数都是一个Function对象。

// 创建了一个能返回两个参数和的函数
var adder = new Function("a", "b", "return a + b");

// 调用函数
adder(2, 6);
//  8

Function和Object(知乎

先有的Object.prototype, Object.prototype构造出Function.prototype,然后Function.prototype构造出Object和Function。

Object.prototype是鸡,Object和Function都是蛋。
下面这张图和实际执行过程并不完全一样,但有助于理解Function和Object的关系。

挖坑:

_proto_(隐式原型)与prototype(显式原型)

  1. 显式原型的作用:用来实现基于原型的继承与属性的共享。
  2. 隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着proto依次查找。

总结:

  1. 对象有属性proto,指向该对象的构造函数的原型对象。
  2. 方法除了有属性proto,还有属性prototype,prototype指向该方法的原型对象。

通过Function扩充功能

可以通过给Object.prototype添加方法,让该方法对所有对象可用,这样的方式对函数、数组、字符串、数字、正则表达式和布尔值同样适用。

可以通过对Functiong.prototype增加方法使得该方法对所有函数可用。

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

使用:

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

(123/20).integer() //-->6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值