JavaScript中的Function对象是函数,函数的用途分为3类:

  1. 作为普通逻辑代码容器;
  2. 作为对象方法;
  3. 作为构造函数。

1.作为普通逻辑代码容器

function multiply(x, y){
return x*y;
}

函数multiply封装了两位数的乘法运算公式:

var product = multiply(128,128); // product = 16384

创建函数实例的方式有3种:

第一种是声明式,即像声明变量一样,将通过function(){  }标识符创建的匿名函数直接赋值给变量,以该变量作为调用时的函数名称:

var multiply = function(x, y){
return x*y;
}

第二种是定义式,即以function关键字后跟函数名称及(){}来直接定义命名函数,前面第一个multiply函数就是通过定义式创建的。

第三种是构造函数式,即通过new运算符调用构造函数Function来创建函数。这种方式极不常用,因此就不作介绍了。

在创建函数的3种方式中,声明式和定义式还存在细微的差别。比如下列代码中的函数采用声明式:

var example = function(){
return 1;
}
example(); var example = function(){
return 2;
}
example();

执行结果如下:

1
2

而如果采用定义式,即:

function example(){
return 1;
}
example(); function example(){
return 2;
}
example();

那么会得到另一种结果:

2
2

即,在采用定义式创建同名函数时,后创建的函数会覆盖先创建的函数。这种差别是由于JavaScript解释引擎的工作机制所导致的。JavaScript解释引擎在执行任何函数调用之前,首先会在全局作用域中注册以定义式创建的函数,然后再依次执行函数调用。由于注册函数时,后定义的函数重写了先定义的函数,因此无论调用语句位于何处,执行的都是后定义的函数。相反,对于声明式创建的函数,JavaScript解释引擎会像对待任何声明的变量一样,等到执行调用该变量的代码时才会对变量求值。由于JavaScript代码是从上到下顺序执行的,因此当执行第一个example()调用时,example函数的代码就是首先定义代码;而当执行第二个example()调用时,example函数的代码又变成了后来定义的代码。

2.作为对象方法

JavaScript在解析代码时,会为声明或定义的函数指定调用对象。所谓调用对象,就是函数的执行环境。如果函数体内有以关键字this声明的变量,则this引用的就是调用对象。

事实上,在普通的函数中,也存在调用对象,只不过这个调用对象是默认的全局window对象而已。例如:

var product = window.multiply(128,128); // product = 16384

这说明,默认情况下,在全局作用域中定义或声明的函数的调用对象就是window。

在面向对象编程中,通常将作为对象成员的函数称为方法。例如:

var dog = {};
dog.name = "heibao";
dog.age = "3 months";
dog.shout = function(){
return "Hello, My name is "+ this.name + " and I am " + this.age + " old!";
}
dog.shout(); // "Hello, My name is heibao and I am 3 months old!"

有意思的是,对象也可以借用其他对象的方法:

var cat = {};
cat.name = "xiaohua";
cat.age = "2 years";
cat.greet = dog.shout;
cat.greet(); // "Hello, My name is xiaohua and I am 2 years old!"

另外,使用函数对象的call和apply方法,还可以动态指定函数或方法的调用对象:

dog.shout.call(cat); // "Hello, My name is xiaohua and I am 2 years old!"

或者

dog.shout.apply(cat); // "Hello, My name is xiaohua and I am 2 years old!"

3.作为构造函数

JavaScript是通过构造函数来模拟面向对象语言中的类的。例如:

function Animal(sort, character){
this.sort = sort;
this.character = character;
}

以Animal作为构造函数,就可以像下面这样创建一个新对象:

var dog = new Animal("mammal","four legs");

创建dog的对象的过程如下:首先,new运算符创建一个空对象({}),然后以这个空对象为调用对象调用函数Animal,为这个空对象添加两个属性sort和character,接着,再将这个空对象的默认constructor属性修改为构造函数的名称(即Animal;空对象创建时默认的constructor属性值是Object),并且将空对象的__proto__属性设置为指向Animal.prototype——这就是所谓的对象初始化。最后,返回初始化完毕的对象。这里将返回的新对象赋值给了变量dog。

dog.sort; // mammal
dog.character; // four legs
dog.constructor; // Animal

聪明的读者结合前面介绍的内容,可能会认为使用new运算符调用构造函数创建对象的过程也可以像下面这样来实现:

var dog = {};
Animal.call(dog, "mammal","four legs");

表面上看,这两行代码与var dog = new Animal(“mammal”,”four legs”);是等价的,其实却不是。虽然通过指定函数的执行环境能够部分达到初始化对象的目的,例如空对象dog确实获得了sort和character这两个属性:

dog.sort; // mammal
dog.character; // four legs
dog.constructor; // Object —— 注意,没有修改dog对象默认的constructor属性

但是,最关键的是新创建的dog对象失去了通过Animal.prototype属性继承其他对象的能力。只要与前面采用new运算符调用构造函数创建对象的过程对比一下,就会发现,new运算符在初始化新对象期间,除了为新对象添加显式声明的属性外,还会对新对象进行了一番“暗箱操作”——即将新对象的constructor属性重写为Animal,将新对象的__proto__属性设置为指向Animal.prototype。虽然手工“初始化对象”也可以将dog.constructor重写为Animal,但根据ECMA262规范,对象的__proto__属性对开发人员是只读的,对它的设置只能在通过new运算符创建对象时由JavaScript解释引擎替我们完成。

JavaScript是基于原型继承的,如果不能正确设置对象的__proto__属性,那么就意味着默认的继承机制会失效:

Animal.prototype.greet = "Hi, good lucky!";
dog.greet; // undefined

事实上,在Firefox中,__proto__属性也是可写的:

Animal.prototype.greet = "Hi, good lucky!";
dog.__proto__ = Animal.prototype;
dog.greet; // Hi, good lucky!

但这样做只能在Firefox中行得通。考虑到在兼容多浏览器,必须依赖于new运算符,才能实现基于原型的继承。

JavaScript中的Function(函数)对象详解的更多相关文章

  1. JavaScript中的鼠标滚轮事件详解

    JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...

  2. php中的PDO函数库详解

    PHP中的PDO函数库详解 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,P ...

  3. delphi中Application.MessageBox函数用法详解

    delphi中Application.MessageBox函数用法详解 Application.MessageBox是TApplication的成员函数,声明如下:functionTApplicati ...

  4. JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)

    面向对象编程:   面向:以什么为主,基于什么模式 对象:由键值对组成,可以用来描述事物,存储数据的一种数据格式 编程:使用代码解决需求   面向过程编程:         按照我们分析好的步骤,按步 ...

  5. JavaScript中typeof和instanceof深入详解

    这次主要说说javascript的类型判断函数typeof和判断构造函数原型instanceof的用法和注意的地方. typeof 先来说说typeof吧.首先需要注意的是,typeof方法返回一个字 ...

  6. JavaScript 中 apply 、call 的详解

    apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已. 原文作者:林 ...

  7. Javascript中的this关键字用法详解

    在javascript里面,this是一个特殊的对象,它不像其他编程语言那样,是存储在实例中的值,直接指向此实例. 而是作为一个单独的指针,在不同的情况之下,指向不同的位置,这也是为什么我们会将它搞混 ...

  8. javascript中6种基本数据类型详解

    javascript中有5中数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String,还有一种复杂数据类型——object,object本质是由一组键值 ...

  9. javascript中的function 函数名(){} 和 函数名:function(){}有什么不同

    function functionName(){};这是定义一个函数 functionName:function(){};是设置一个对象的方法. 下面举一个例子: <html> <h ...

  10. JavaScript中继承的实现方法--详解

    最近看<JavaScript王者归来>中关于实现继承的方法,做了一些小总结: JavaScript中要实现继承,其实就是实现三层含义:1.子类的实例可以共享父类的方法:2.子类可以覆盖父类 ...

随机推荐

  1. 开始学习node.js了,第一节,fs文件系统 【fs.rename】重命名文件/文件夹

    var fs=require('fs');fs.rename('c:\\a','c:\\a2',function(err){ if(err) console.log('error:'+err);}); ...

  2. 编写高质量代码--改善python程序的建议(八)

    原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...

  3. Mustache.js前端模板引擎源码解读

    mustache是一个很轻的前端模板引擎,因为之前接手的项目用了这个模板引擎,自己就也继续用了一会觉得还不错,最近项目相对没那么忙,于是就抽了点时间看了一下这个的源码.源码很少,也就只有六百多行,所以 ...

  4. 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  5. sql-函数avg,count,max,min,sum

     常用函数 AVG (平均) COUNT (计数) MAX (最大值) MIN (最小值) SUM (总合) 运用函数的语法是: SELECT "函数名"("栏位名&qu ...

  6. Mysql数据库登录问题:Your password has expired.

    ERROR 1862 (HY000): Your password has expired. To log in you mustchange it using a client that suppo ...

  7. 【BZOJ-1984】月下“毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1314  Solved: 416[Submit][Status][Discu ...

  8. 学习笔记--(平衡树)splay

    坑爹的splay,毁我青春,耗我钱财,颓我精力 是一种用于保存有序集合的简单高效的数据结构.伸展树实质上是一个二叉查找树.允许查找,插入,删除,删除最小,删除最大,分割,合并等许多操作,这些操作的时间 ...

  9. 【心得&&体会】

    ★2016.1.1★ 很早就想写这样的一篇blog了,但一直没有抽空去实现,新的一年感觉应该有所改变,故深夜提笔(码字) NOIP卡掉和连续两次月考爆炸,这段时间确实心理不舒服,调节的也不是很到位,但 ...

  10. codeforces 719A:Vitya in the Countryside

    Description Every summer Vitya comes to visit his grandmother in the countryside. This summer, he go ...