javascript Function()

JavaScript中的Function对象是函数,函数的用途分为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运算符,才能实现基于原型的继承

 

转载于:http://blog.sina.com.cn/s/blog_81adceb001012n51.html

转载于:https://www.cnblogs.com/ellisonDon/archive/2012/08/12/2634421.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java基础之线程(1)

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初…

poj 1274 The Perfect Stall

2019独角兽企业重金招聘Python工程师标准>>> The Perfect Stall Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16888 Accepted: 7721 Description Farmer John completed his new barn just last week, complete with all the latest milkin…

C++远征之封装篇——常对象成员、常成员函数

一、常对象成员 二、常成员函数 (1)常成员函数中不能修改数据成员的值 (2)不能修改的原因 每个函数都默认带了一个this指针的,该指针指向该类的实例。当使用const来修饰时,其实是const Coordinate* this。这…

PHP建站环境搭建:汇总网上常见的1键安装包

PHP的程序很火,像博客:Wordpress、论坛:Discuz!、SNS:UCenter Home、CMS:DedeCMS等等都是比较流行的PHP程序,大家都在使用PHP类的程序,但对于很多初学者来说,直接上传到虚拟空间上一…

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和文章作者:Yx.Ac 文章来源:勇幸|Thinking (http://www.ahathinking.com) 转载请注明,谢谢合作。 以后新博客写的文章挑一些粘过来&#…

JEECMS编辑漏洞及随便拿webshell,啊哈哈

JEECMS是基于java技术开发,继承其强大、稳定、安全、高效、跨平台等多方面的优点 采用SpringMVC3Spring3Hibernate3Freemarker主流技术架构 安全性做得非常变态,当网站安装完成后就不再允许执行任何目录下的jsp文件了(web.xml配置了过滤器禁…

内核通识——linux内核的简介

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 内核下载 下载地址:www.kernel.org 下载地址:Index of /sites/ftp.kernel.org/pub/linux/kernel/ 本栏目文章2.6.35.7版本为例进行说明。 一、内核功能 1、操作系统的含义 操…

端口列表详解

tyle"margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial; color:rgb(51,51,51); text-align:left"> TCP 2Death TCP 11Skun TCP 12Bomber TCP 16Skun TCP 17Skun TCP 18消息传输协议,skun TCP 19Skun TCP 20FTP Data,Amanda TCP 21文件传…

C++之内存管理

1.申请内存:int *p new int;释放内存:delete p; 2.申请块内存:int *arrnew int[10];释放:delete []arr; 3.申请内存需要判断是否成功,释放内存需要设空指针 4.new与delete配套使用 转载于:https://www.cnblogs.com/xjyxp/p/11236…

Android 调用分享框

平时打开某些应用的分享选项时,经常可以看到同时分享到google play, 豌豆荚,91助手等弹出框,具体怎样实现的呢? 可以参考下面的代码 Uri uri Uri.parse("market://details?id"Constant.PACKAGE_NAME);Intent intent …

内核通识——linux内核源码(2.6.35.7版本)的目录结构

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、文件 (1)Kbuild文件 Kbuild是kernel build的缩写,就是内核编译的意思。这个文件就是linux内核特有的内核编译体系需要用到的文件。 (2&#xff09…

【原创】自制PCB经验教训之一:版图打印篇

看了篇帖子《用感光电路板自制PCB攻略(网友电子白菜撰写)》,于是前几天在淘宝上买了一批PCB DIY工具和材料回来,想自己弄个试试,岂料障碍重重,甚至于酿成大祸... 首先是PCB打印的软件设置问题,我…

magento cms page、登錄頁面修改(增加)breadcrumbs

由於magento的cms功能有限,在cms page的角度來看,差不存在cms的category,所以cms page的breadcrumbs只會出現單層的結構(HOME->About Us), 要想模仿出分層次的結構,就需要修改cbreadcrumbs了。 修改方法如下&#x…

分享一套非常不错的bootstarp3.0.2响应式模板

2019独角兽企业重金招聘Python工程师标准>>> 这是销量第一的bootstrap 响应式后台管理模板,每套模板都是我用20美金买回来的话不多说,下面是五个模板的演示地址,你看到的,就是你可以下载到的。都是收费模板。 官方演示…

内核配置与编译——编译初体验

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、获取内核源码 第一种是kernel.org的官方版本,第二种是三星移植过的,第三种是X210的移植版本。讲课时使用第三种内核,移植实验使用第二种内核。九鼎配置好的k…

10 个理由让你继续干 IT

1.钱,钱,钱对,我们努力工作就是为了赚钱,而IT专业人士的努力工作的确得到了很好的补偿。报酬不仅仅是好而已,而是非常棒。根据美国劳工部《2010年美国 就业与报酬情况概览》(表6,PDF&#xff09…

脱机下载至校验成功的脚本

今天又差点在 root 权限下破坏了系统 (归功于破坏力极强的 build-sysroot.sh), 心想逐步把写过的一些小工具备份。 sureget #!/bin/sh if [ -z $2 ]; thenfnamebasename "$1" elsefname$2 fiwhile true; do[ -f $fname ] && rm -f $fnamewget -c $1 -O $fnam…

MySQL同步状态双Yes的假象及seconds_behind_master的含义

近期由于特殊原因有一台主库宕机了一个小时没有处理,说起来这是个挺不好啥意思的事情,但是由于这个事情反而发现个比较诡异的情况,那就是在主库宕机一个小时候后,监控才发出从库IO thread中断的报警,也就是说在那一个小…

内核配置与编译——内核的配置原理

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 概述 编译内核前需要进行两步配置,即先make x210ii_qt_defconfig,然后再make menuconfig。第一步如果成功,则会提示“configuration written to .config”。注意…

gluPickMatrix和glReadPixels

gluPickMatrix的使用2008年12月03日 星期三 23:40void gluPickMatrix(GLdouble x,GLdouble y,GLdouble width,GLdouble height,GLint viewport[4]); 它是用来根据当前鼠标选择区域生成一个相应的投影矩阵的。这里面头两个参数不是这个选择区域的左上角位置,而是整个…