利用javascript构造器的构造函数返回一个函数有什么好处和意义

(js)使用new对函数进行构造调用 - 简书
(js)使用new对函数进行构造调用
js中的函数有两种调用方式,一种是通过普通的声明之后进行的调用。一种是通过new关键字进行构造调用。普通的调用就是依次执行函数内部的函数语句,如果有返回值则返回返回值,如果没有则函数内部的声明周期结束。但是,函数还有另一个调用方式,使用new关键字,将函数当做构造函数。js中没有所谓独立出来的构造函数的概念,所有的函数都用同样的方式声明,所以有了new这个关键字,js(ES6之前)只能通过这种方式实现构造器的构造。那么使用new关键字跟普通的调用有什么区别呢?
使用new关键字,比普通的函数调用,主要分为以下四个步骤:
建立一个空对象 。
将函数内部的this修正到上面新建的对象上来。
继续执行函数的其它语句,并且将上面新建的对象的[[prototype]]属性(ES6中称为"__proto__")指向该构造函数。
如果函数没有返回值或着函数有返回值,但是该返回值不是对象的话,则返回第一步建立的对象;如果函数有返回值,且返回值是对象的话,则忽略第一步建立的对象,返回默认返回的对象。
稍后我们会对上面的四句话逐一解析,首先我们看一看函数调用的两种方式:
var fun = function () {
var a = 2;
console.log(a * 2);
//新建函数fun
new fun();
这样看来,两者似乎没有区别,但是这里要注意,使用new进行构造调用时,函数是有返回值的。
var return1 = fun();
var return2 = new fun();
console.log(return1);
//undefined
console.log(return2);
上面的return2并没有返回一个函数。
typeof return2;
Object.prototype.toString.call(return2);
//[object Object]
其实它会返回一个空的对象。这也就是上面使用new关键词的第一步,内部创建一个新的空对象。
那么当函数内部有this时,结果会是怎样的呢?
var fun = function () {
this.a = 2;
console.log(this.a * 2);
new fun();
var return1 = fun();
var return2 = new fun();
console.log(return1);
//undefined
console.log(return2);
//{ a: 2 }
使用new关键字后,在函数内部如果出现了this,则自动将this指向内部新建的对象上。最后返回时,因为this的缘故,对象上新建了a属性,并且赋值返回。
修正定义的对象Object的[[prototype]]虽然实例上的[[prototype]]属性__proto__是ES6才作为规范出版的。但是在这之前chrome已经支持__proto__属性,他指向对象的原型。
原型的问题相当复杂,单独拿出来也可以当好几篇文章的量来讲。但是这并不是本文的重点。但是每一个对象从根部来说,继承自Object。而Object.prototype上面定义了一些方法,有类似toString,valueOf等等等方法。对于对象来说,支持通过属性链和方法链向上查询。所以在一个对象实例中,如果没有定义toString方法,但它还可以向上查询,找到原型中的toString方法,进行调用。
同时的,有很多元素通过Object实现继承。比如Function, Array, RegExp等等对象,它们也是对象,但是却是继承来自Object。
在这里,内部定义的对象,让他继承来自构造函数。
最后一步,也是最容易被忽略的一步,那就是当构造函数存在返回值时,并且返回值为对象时,返回对象而不返回之前定义的对象。
var fun = function () {
this.a = 1;
var obj = new fun();
当然,上面说的Function,Array,RegExp也算Object的一种,如果返回他们同样也会阻止默认的对象返回。
var fun = function () {
this.a = 1;
return function () {
this.a = 2;
var obj = new fun();
//function () { this.a = 2; }javascript中构造函数的返回值问题和new对象的过程
首先明确一点:javascript中构造函数是不需要有返回值的,这一点跟java很类似。可以认为构造函数和普通函数的最大差别就是:构造函数中没有return语句,普通函数可以有return语句;构造函数中会使用this关键字定义成员变量和成员方法,普通的函数不会使用this关键字定义成员变量和方法。
function Person(name,sex)
this.name =
this.sex =
//return 1;
//return "aty";
return {"returnValue":11};
//new关键字会被认为是创建对象
var aObj = new Person("11",1);
alert(aObj.returnValue);//11
alert(aObj.name);//undefined
构造函数不需要显示的返回值。使用new来创建对象(调用构造函数)时,如果return的是非对象(数字、字符串、布尔类型等)会忽而略返回值;如果return的是对象,则返回该对象。
下面简单介绍下,javascript中new对象的过程:如var myObj = newPerson(“aty”,25);
1.创建一个空的Object对象.var obj = new Object();
2.将构造函数Person中this指向刚创建的obj对象
3.将创建的obj的__proto__指向构造函数Person的prototype。这一步是建立对象和原型直接的对应关系。firefox下通过
对象的__proto__属性能够访问到原型,IE下则没有暴露出相应的属性。
4.执行构造函数Person()中的代码OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;
欢迎您订阅我们的技术周刊
我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,
欢迎分享您的观点,经验,技巧,心得
让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;
本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(
订阅邮件周刊
JavaScript中的继承,构造函数以及new关键字的作用
注意 转载须保留原文链接,译文链接,作者译者等信息。&&
通常一个构造函数是这样子的,它带有一个area的原型方法,在构造函数中传入长、宽并计算面积。var Shape = function(width, height) {
this.width =
this.height =};Shape.prototype.area = function() {
return this.width * this.height};var shape = new Shape(20, 30);shape.area();> 600输出很完美,这也是经典JavaScript实现继承的方法,通过prototype添加对另外一个对象的引用。不过一部分JavaScript程序是非常讨厌new关键字的,这个关键字有太浓烈的Java烙印了,而且掩盖了JavaScript基于原型的本质,降低了程序员使用JS语言的效率,因此你想把它省了,看看结果?注* "JavaScript The Good Parts“的作者Douglas Crockford 曾写道
"A much better alternative is to not use new at all." (page 49),
参见另一程序员对AngularJS的吐嘈, (吐嘈之一就是里面到处都是new)var shape = Shape(20, 30);shape.area();> TypeError: Cannot read property 'area' of undefined道理再简单不过了,你只不过是执行了一个函数,但是这个函数并没有返回值,所以shape必然是undefined,看来new关键作用之一跟Java是一样的,就是实例化此对象并返回这个对象本身。所以你又试改写了一下函数:var Shape = function(width, height) {
var self =
self.area = function() {
return width *
var shape = Shape(20, 30);shape.area();
> 600不错,It works!也不用实例化Shape了,看上去一切正常,代码看上去更简单了,隐藏了不必要的属性,不过似乎你没有意识到你设计了一个潜在的更大的坑,尝试在console中打印这些:area> function () { return self.width * self. }为什么are变成了全局变量?你不死心,又在window里打印window.area> function () {
return width *
}结果还一样,其实这一现象在"Javascript: The Good Parts"一书中有很好的解析:If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning. (page 49)如果你在一个构造函数中忘了加new,那么这个新对象就不会绑定到新的实例上,不幸的是,它会绑定到全局对象上,你就会影响全局变量。这是非常糟糕的。没有编译警告,并且没有运行时的警告。(第49页)看来在function函数内使用this绑定公开属性是非常危险的,因为你不确定会不会有人忘写了一个new,或者故意不加一个new,也许这就是为什么基于function的构造函数现在用得越来越少的原因吧,其实解决的办法非常简单,只需更改一处。var Shape = function(width, height) {
var self = {};
self.area = function() {
return width *
}};var shape = Shape(20, 30);shape.area();
>600其实还有很多其它的解决方案,还有一些开源项目甚至根本不使用构造函数,在此不再累述。
&热门文章 - 分享最多
&相关阅读 - 大话编程
&关键字 - JavaScript
&欢迎订阅 - 技术周刊
我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;
我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

我要回帖

更多关于 javascript 构造数组 的文章

 

随机推荐