JavaScript中以构造函数的方式调用函数
转自:http://www.cnblogs.com/Saints/p/6012188.html
构造器函数(Constructor functions)的定义和任何其它函数一样,我们可以使用函数声明、函数表达式或者函数构造器(见以前的随笔)等方式来构造函数对象。函数构造器和其它函数的区别在与它们的调用方式不同。
要以构造函数的方式调用函数,只需要在调用时在函数名称前加new 关键字,比如:function whatsMyContext(){ return this; }; 调用:new whatsMyContext();
以构造函数的方式调用函数是JavaScript中非常强大的特性,下面来探究它的神秘之处:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function Ninja() { this.skulk = function() { return this; };}var ninja1 = new Ninja();var ninja2 = new Ninja();assert(ninja1.skulk() === ninja1, "The 1st ninja is skulking");assert(ninja2.skulk() === ninja2, "The 2nd ninja is skulking"); |
上面的demo中,首先定义了一个构造器函数,这个构造器函数会在函数的上下文对象上创建一个名为shulk的函数属性。接着通过以构造函数的方式调用函数Ninja来创建两个Ninja(类型)对象,并且分别被ninja1和ninja2引用,最后通过自定义函数assert来验证每个对象的skulk方法,每个shulk方法应该返回每次以new的方式调用Ninja时构造出来的函数对象。
下面来看一下这个过程中发生了什么:
1.一个全新的空的对象被创建;
2.这个空的对象被传递到构造器函数并且作为它的this参数,因此成为了这个构造器函数的上下文对象;
3.在这个新的空的对象上添加属性,shulk
4.这个被构造出来的对象被作为函数的返回值返回。

使用构造器函数的目的是为了创建新的对象,对这个对象进行操作并且这个对象作为构造器函数的返回值返回。任何和这个目的无关的函数都不适合作为构造器函数。在函数没有返回值的时候以构造函数的方式调用这个函数会返回新创建的上下文对象,那么在函数返回一个值(基本类型)的时候会有什么变化吗?看下面的例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function Ninja() { this.skulk = function () { return true; }; return 1}assert(Ninja() === 1,"Return value honored when not called as a constructor");var ninja = new Ninja();assert(typeof ninja === "object","Object returned when called as a constructor");assert(typeof ninja.skulk === "function","ninja object has a skulk method"); |
运行上面的例子,所有的断言都可通过,事实上Ninja函数返回一个简单类型的值1对代码的执行没有产生任何影响:如果以函数的方式调用Ninja它将返回1,而以构造函数的方式调用它,会返回new产生的函数上下文对象。 如果函数返回另一个对象会发生什么?
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var puppet = { rules: false};function Emperor() { this.rules = true; return puppet;}var emperor = new Emperor();assert(emperor === puppet, "The emperor is merely a puppet!");assert(emperor.rules === false, "The puppet does not know how to rule!"); |
这次和上面的例子不同,首先创建一个puppet对象并把它的rules属性设置为false;接着定义一个名为Emperor的函数,并且把它的上下文变量的rules属性设置为true,但是函数最后却把全局的puppet对象作为返回值返回。再接着以构造函数的方式调用Emperor函数;这样产生一个有歧义的情况,我们获得了一个作为函数上下文的对象(this),但是却返回了一个完全不同的对象,这种情况下哪一个对象会被返回呢?
根据后面assert函数的断言测试可以看到,被返回的是puppet函数。下面来总结一下:
1.如果构造器函数返回一个对象,这个对象会作为new表达式的返回值返回,在以new方式调用函数时产生的作为函数上下文(this)的对象会被丢弃;
2.如果构造器函数没有返回对象(返回值为值类型),这个返回的值会被丢弃,以new方式调用函数时产生的作为函数上下文(this)的对象会被返回。
构造器函数的代码习惯:
构造器函数的目的是为函数调用时产生的上下文对象进行初始化并返回这个对象,虽然这些构造器函数可以以函数或者方法的形式调用,通常情况下那么做并没有什么意义,比如:
function Ninja() {
this.skulk = function() {
return this;
};
}
var whatever = Ninja();
简单的以函数方式调用Ninja,skulk会被绑定到全局变量window上(非严格模式下),这不是特别有用的操作,在严格模式下更没有意义,因为上下文对象this为undefined,因此会抛出不能为undefined设置属性的异常。在非严格模式下,这样做很容易出现莫名其妙的状况,这很难被察觉到因为它没有抛出任何异常。
因为构造器函数也是普通的函数,只是使用不同的方式调用而已,通常情况下,对于构造器函数的定义有不同的命名习惯:
以动词开头用以描述它是来做什么的并且首字母小写的函数名适合普通的函数或者对象的方法;构造器函数的命名通常是一个名词,用来描述要创建的对象,首字母通常大写。
JavaScript中以构造函数的方式调用函数的更多相关文章
- JavaScript中的构造函数和工厂函数说明
在cnblog上看到一篇文章,讲解JS中的构造函数和工厂函数,觉得讲的真好 JavaScript中的工厂函数和构造函数都能用来创建一个对象,我们可以来看看下面的例子 构造函数 function cre ...
- 博文推荐】Javascript中bind、call、apply函数用法
[博文推荐]Javascript中bind.call.apply函数用法 2015-03-02 09:22 菜鸟浮出水 51CTO博客 字号:T | T 最近一直在用 js 写游戏服务器,我也接触 j ...
- JavaScript中定义类的方式详解
本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的exte ...
- JavaScript中的bind,call和apply函数的用法和区别
一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下 首先要理解的第一个概念,JavaScript中函数调用的方式, ...
- JavaScript中创建数组的方式!
JavaScript中创建数组的方式! 利用数组字面量 // 1 直接量 console.log(Array.prototype); var arr = [1, 2, 4, 87432]; // 注意 ...
- JavaScript中的构造函数和原型!
JavaScript中的原型! 原型的内容是涉及到JavaScript中的构造函数的 每一个构造函数都有一个原型对象!prototype 他的作用是 共享方法!还可以扩展内置对象[对原来的内置对象进行 ...
- Javascript中call、apply、bind函数
javascript在函数创建的时候除了自己定义的参数外还会自动新增this和arguments两个参数 javascript中函数也是对象,call.apply.bind函数就是函数中的三个函数,这 ...
- JavaScript中bind、call、apply函数用法详解
在给我们项目组的其他程序介绍 js 的时候,我准备了很多的内容,但看起来效果不大,果然光讲还是不行的,必须动手.前几天有人问我关于代码里 call() 函数的用法,我让他去看书,这里推荐用js 写服务 ...
- JavaScript中bind、call、apply函数使用方法具体解释
在给我们项目组的其它程序介绍 js 的时候,我准备了非常多的内容,但看起来效果不大,果然光讲还是不行的,必须动手. 前几天有人问我关于代码里 call() 函数的使用方法.我让他去看书,这里推荐用js ...
随机推荐
- 为什么重写equals()必须重写hashCode()
主要原因是因为hashCode是用对象的内部地址转换成一个整数的,而equals比较得是两个对象,或者是两个对象的内容 如果你重写了equals,而保留hashCode的实现不变,那么很可能两个对象明 ...
- windows10安装composer并解决和xdebug的冲突
环境:windows10,php7,php安装目录C:\php\,php目录已加入windows的PATH. 1.下载composer,在Windows下最简单的办法是下载composer.phar并 ...
- FreeMarker 语法
copy自http://demojava.iteye.com/blog/800204 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...
- oracle 字段类型详解
CHAR 固定长度字符串 最大长度2000 bytes VARCHAR2 可变长度的字符串 最大长度4000 bytes 可做索引的最大长度749 NCHAR 根据字符集而定的固定长度字符串 最大长度 ...
- linux共享文件夹
mnt中没有 hgfs,重新安装vm tools后问题解决
- 设计模式 -- 解释器模式(Interpreter Pattern)
2015年12月15日00:19:02 今天只看了理论和demo,明天再写文章,跑步好累 2015年12月15日21:36:00 解释器模式用来解释预先定义的文法. <大话设计模式>里面这 ...
- CodeForces 705A Hulk
水题. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #includ ...
- L3-001. 凑零钱
L3-001. 凑零钱 题目链接:https://www.patest.cn/contests/gplt/L3-001 动态规划 这道题一看就知道应该用背包思想来做,不过想了好久没什么思路(dp实在是 ...
- 微信小程序Tabbar文字在真机不显示
按照官方文档在json中定义好了Tabbar后,在模拟器上显示没问题,而在真机上不显示Tabar文字. 让我很苦笑不得的原因是: 在app.json定义Tabbar文字选中态和非选中态颜色时我用了英文 ...
- 统计C语言程序行数
补充前一篇中统计C语言程序行数的程序 写得比较匆忙,可能有些失误,等弄明白GitHub的用法并完善程序后再补充完整代码链接 没有写成函数,但经过简单修改可以作为一个计算或判断函数使用 判断算法主要为以 ...