摘要:关于操作符,我的理解一里有进一步描述举例即是构造函数在本例中,对象具有特定的类型,可称之为一个对象。用作对象类型的标记使用构造函数创建的对象可以很方便的检查它们的类型,比如为对象创建共享属性这可能是使用构造函数最重要的理由了。
JavaScript 中的构造器 什么是构造器?
构造器也叫构造函数,它就是一个普通的函数,只不过它的主要目的是用于和 new 操作符配合来创建特定类型的对象。(关于 new 操作符,我的理解 JavaScript(一)里有进一步描述)
举例:
var me = new Person("Albert", "Yu", 32); // Person 即是构造函数
在本例中,me 对象具有特定的类型,可称之为:一个 Person 对象。而 Person 就是它的类型名字。
那么构造函数内部又是如何工作的?
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; };
和普通的函数相比,有两个明显的区别,解释如下:
函数名称首字母大写:这其实只是一个约定而不是强制行为,绝大多数 JavaScript 程序员都会遵守这个约定,即首字母大写的函数名是一个构造函数;当然,首字母小写的函数一样可以充当构造函数
使用 this 捆绑局部变量:一般性的函数都是直接创建本地变量来保存值,而构造函数使用 this 捆绑局部变量是为了配合 new 操作符。因为 new 操作符会创建一个新对象,并且把新对象绑定在构造函数内部的 this 上,于是被捆绑在 this 上的局部变量事实上就成为新对象的属性了
因此,这样的构造函数所创建的对象大致等价于:
var me = { firstName: "Albert", lastName: "Yu", age: 32 };
那么既然如此,我们为啥还要写构造函数?
构造函数的用处 1. 用作创建对象的模板如果只需要创建少量对象(比如一个),编写构造函数的确没太大意义。但是遇到需要重复创建对象的场合,构造函数显然是 DRY(Don"t Repeat Youself)的上佳选择。
不仅仅是为了减少重复编码的工作量,而且经常会有对于输入参数进行验证并抛出错误的功能设计,也可以借助构造函数来完成。
2. 用作对象类型的标记使用构造函数创建的对象可以很方便的检查它们的类型,比如:
var me = new Person("Albert", "Yu", 32); var you = { firstName: "Super", lastName: "Man", age: 18 }; console.log(me instanceof Person); // true console.log(you instanceof Person); // false3. 为对象创建共享属性
这可能是使用构造函数最重要的理由了。基于原型继承的 JavaScript 可以很方便的为对象扩充成员属性:
var me = new Person("Albert", "Yu", 32); me.firstName; // "Albert" me.lastName; // "Yu" me.age; // 32 // 我想要标记所有的 Person 对象都是活着的…… Person.prototype.isAlive = true; me.isAlive; // true // 我还想要输出用户的全名…… me.firstName + " " + me.lastName; // "Albert Yu" // 这样太二了吧? Person.prototype.fullName = function() { return [this.firstName, this.lastName].join(" "); }; me.fullName(); // "Albert Yu" // 嗯,文艺多了……
有一点特别需要注意的!
使用构造函数创建对象一定要使用 new 操作符
这是因为(再次强调):真正创建新对象的不是构造函数,而是 new 操作符。构造函数只是充当新对象的模板,它接收 new 创建的对象然后用模板填充这个对象的属性设置。
鉴于此,忘记使用 new 的话是比较危险的。因为没有 new 创建新对象的时候,构造函数内的 this 会被捆绑给全局对象,通常是 window(浏览器)或者 global(Node.js),让我们看看会发生啥事儿吧……
var me = new Person("Albert", "Yu", 32); me.firstName; // "Albert" var you = Person("Super", "Man", 18); you.firstName; // undefined... WTF?! this.firstName; // "Super"...Shiiiit! // 上面的 this 是全局对象
那么如何改进构造函数呢?简单。
function Person(firstName, lastName, age) { if (this instanceof Person) { // 想一想还有没有其他的判断方式? this.firstName = firstName; this.lastName = lastName; this.age = age; } else { throw new Error("不用 `new` 是不可以的哟~~~"); } }
这个思路就是先判断构造函数接收到的 this 是不是自己的实例,若是则一切好说,若不是则抛出错误强制用户使用 new 操作符。
当然,这个改进虽然可靠了,但还是不够“聪明”,要是能让构造函数自己判断来自动使用 new 该多好呀!没错,这是更好地方式,不过在这里我就不演示了,还是由您自己来动手实践一下吧?(提示:考虑一下构造函数的原型对象。如果想不出来的话不要紧,我们以后接着聊)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77965.html
摘要:第四点也要着重讲下,记住构造函数被操作,要让正常作用最好不能在构造函数里 4) this、new、call和apply的相关问题 讲解this指针的原理是个很复杂的问题,如果我们从javascript里this的实现机制来说明this,很多朋友可能会越来越糊涂,因此本篇打算换一个思路从应用的角度来讲解this指针,从这个角度理解this指针更加有现实意义。 下面我们看看在ja...
摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...
摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...
摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...
阅读 904·2021-11-22 13:53
阅读 2536·2021-10-15 09:40
阅读 1003·2021-10-14 09:42
阅读 3479·2021-09-22 15:59
阅读 889·2021-09-02 09:47
阅读 2371·2019-08-30 15:54
阅读 1440·2019-08-29 17:14
阅读 400·2019-08-29 15:15