JavaScript深切系列第十四篇,解说建立对象的各种体式格局,以及优瑕玷。
写在前面
这篇文章解说建立对象的各种体式格局,以及优瑕玷。
然则注重:
这篇文章更像是笔记,由于《JavaScript高等程序设计》写得真是太好了!
1. 工场形式
function createPerson(name) {
var o = new Object();
o.name = name;
o.getName = function () {
console.log(this.name);
};
return o;
}
var person1 = createPerson('kevin');
瑕玷:对象没法辨认,由于一切的实例都指向一个原型
2. 组织函数形式
function Person(name) {
this.name = name;
this.getName = function () {
console.log(this.name);
};
}
var person1 = new Person('kevin');
长处:实例能够辨认为一个特定的范例
瑕玷:每次建立实例时,每一个要领都要被建立一次
2.1 组织函数形式优化
function Person(name) {
this.name = name;
this.getName = getName;
}
function getName() {
console.log(this.name);
}
var person1 = new Person('kevin');
长处:处理了每一个要领都要被从新建立的题目
瑕玷:这叫啥封装……
3. 原型形式
function Person(name) {
}
Person.prototype.name = 'keivn';
Person.prototype.getName = function () {
console.log(this.name);
};
var person1 = new Person();
长处:要领不会从新建立
瑕玷:1. 一切的属性和要领都同享 2. 不能初始化参数
3.1 原型形式优化
function Person(name) {
}
Person.prototype = {
name: 'kevin',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
长处:封装性好了一点
瑕玷:重写了原型,丧失了constructor属性
3.2 原型形式优化
function Person(name) {
}
Person.prototype = {
constructor: Person,
name: 'kevin',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
长处:实例能够经由历程constructor属性找到所属组织函数
瑕玷:原型形式该有的瑕玷照样有
4. 组合形式
组织函数形式与原型形式双剑合璧。
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
长处:该同享的同享,该私有的私有,运用最普遍的体式格局
瑕玷:有的人就是愿望全部都写在一同,即更好的封装性
4.1 动态原型形式
function Person(name) {
this.name = name;
if (typeof this.getName != "function") {
Person.prototype.getName = function () {
console.log(this.name);
}
}
}
var person1 = new Person();
注重:运用动态原型形式时,不能用对象字面量重写原型
诠释下为什么:
function Person(name) {
this.name = name;
if (typeof this.getName != "function") {
Person.prototype = {
constructor: Person,
getName: function () {
console.log(this.name);
}
}
}
}
var person1 = new Person('kevin');
var person2 = new Person('daisy');
// 报错 并没有该要领
person1.getName();
// 解释掉上面的代码,这句是能够实行的。
person2.getName();
为了诠释这个题目,假定最先实行var person1 = new Person('kevin')
。
假如对 new 和 apply 的底层实行历程不是很熟悉,能够浏览底部相干链接中的文章。
我们回忆下 new 的完成步骤:
起首新建一个对象
然后将对象的原型指向 Person.prototype
然后 Person.apply(obj)
返回这个对象
注重这个时刻,回忆下 apply 的完成步骤,会实行 obj.Person 要领,这个时刻就会实行 if 语句里的内容,注重组织函数的 prototype 属性指向了实例的原型,运用字面量体式格局直接掩盖 Person.prototype,并不会变动实例的原型的值,person1 依然是指向了之前的原型,而不是 Person.prototype。而之前的原型是没有 getName 要领的,所以就报错了!
假如你就是想用字面量体式格局写代码,能够尝试下这类:
function Person(name) {
this.name = name;
if (typeof this.getName != "function") {
Person.prototype = {
constructor: Person,
getName: function () {
console.log(this.name);
}
}
return new Person(name);
}
}
var person1 = new Person('kevin');
var person2 = new Person('daisy');
person1.getName(); // kevin
person2.getName(); // daisy
5.1 寄生组织函数形式
function Person(name) {
var o = new Object();
o.name = name;
o.getName = function () {
console.log(this.name);
};
return o;
}
var person1 = new Person('kevin');
console.log(person1 instanceof Person) // false
console.log(person1 instanceof Object) // true
寄生组织函数形式,我个人认为应当如许读:
寄生-组织函数-形式,也就是说寄生在组织函数的一种要领。
也就是说打着组织函数的幌子挂羊头卖狗肉,你看建立的实例运用 instanceof 都没法指向组织函数!
如许要领能够在特别情况下运用。比方我们想建立一个具有分外要领的特别数组,然则又不想直接修正Array组织函数,我们能够如许写:
function SpecialArray() {
var values = new Array();
for (var i = 0, len = arguments.length; i < len; i++) {
values.push(arguments[i]);
}
values.toPipedString = function () {
return this.join("|");
};
return values;
}
var colors = new SpecialArray('red', 'blue', 'green');
var colors2 = SpecialArray('red2', 'blue2', 'green2');
console.log(colors);
console.log(colors.toPipedString()); // red|blue|green
console.log(colors2);
console.log(colors2.toPipedString()); // red2|blue2|green2
你会发明,实在所谓的寄生组织函数形式就是比工场形式在建立对象的时刻,多运用了一个new,实际上二者的结果是一样的。
然则作者多是愿望能像运用一般 Array 一样运用 SpecialArray,虽然把 SpecialArray 当做函数也一样能用,然则这并非作者的本意,也变得不文雅。
在能够运用其他形式的情况下,不要运用这类形式。
然则值得一提的是,上面例子中的轮回:
for (var i = 0, len = arguments.length; i < len; i++) {
values.push(arguments[i]);
}
能够替换成:
values.push.apply(values, arguments);
5.2 稳妥组织函数形式
function person(name){
var o = new Object();
o.sayName = function(){
console.log(name);
};
return o;
}
var person1 = person('kevin');
person1.sayName(); // kevin
person1.name = "daisy";
person1.sayName(); // kevin
console.log(person1.name); // daisy
所谓稳妥对象,指的是没有大众属性,而且其要领也不援用 this 的对象。
与寄生组织函数形式有两点差别:
新建立的实例要领不援用 this
不运用 new 操作符挪用组织函数
稳妥对象最适合在一些平安的环境中。
稳妥组织函数形式也跟工场形式一样,没法辨认对象所属范例。
下一篇文章
相干链接
《JavaScript深切之call和apply的模仿完成》
深切系列
JavaScript深切系列目次地点:https://github.com/mqyqingfeng/Blog。
JavaScript深切系列估计写十五篇摆布,旨在帮人人捋顺JavaScript底层学问,重点解说如原型、作用域、实行上下文、变量对象、this、闭包、按值通报、call、apply、bind、new、继续等难点观点。
假如有毛病或许不严谨的处所,请务必赋予斧正,非常谢谢。假如喜好或许有所启示,迎接star,对作者也是一种勉励。