这两个人声明之间的主要区别是什么?
通过构造函数:
var Person = function (name, age) {
this.name = name;
this.age = age;
this.setName = function (name) {
this.name = name;
};
this.setAge = function (age) {
this.age = age;
};
};
var bob = new Person('Bob', 15);
通过对象文字:
var defaultPerson = {
name: '',
age: '',
setName: function (name){
this.name = name;
},
setAge: function(age){
this.age = age;
}
};
defaultPerson.setName('Fill');
defaultPerson.setAge(15);
是否对这两个创建的对象施加了一些限制?
答案 0 :(得分:3)
使用构造方法,您可以创建多个实例(非常相当于一个类):
var person1 = new Person('a',12);
var person2 = new Person('b',13);
而另一种方式只会创建一个类的实例。
var person1 = {
// blah
};
对于person2,您需要创建一个新对象:
var person2 = {
// blah
};
在ctor方式中你也可以:
1.运行代码
2.传递参数。
3.拥有原型并支持继承\扩展对象。
答案 1 :(得分:2)
这是关于Javascript和继承方法中的OO的广泛问题。我无法在帖子的答案中覆盖它,你应该进行一些搜索和阅读,但这里有一些要考虑的要点:
在第二种方法中,您刚刚创建了一个普通对象并使用了它的方法。但我假设你真正想要做的是将其作为原型来创建其他对象。请考虑以下代码:
var fill = Object.create(defaultPerson);
// fill will be created and its internal prototype is set to the defaultPerson object.
第二种方法通常被称为Pure Prototypal Inheritance,其中一些包括我自己,发现它对Javascript更自然。
第一种方法是对经典OOP语言中的构造函数的模仿。现在在ES6(2015)中通过添加关键词'calss,extends'来进一步加强;
毕竟;两者都是在Javascript中创建对象和实现继承的有效方法。做出选择并坚持方便。
答案 2 :(得分:0)
主要有三个不同之处:
使用文字...
创建对象时.__proto__
属性设置为Object.prototype
.constructor
设置为function Object(){...}
但是,如果您运行此代码......
function a(){}
var obj = new a();
//then
obj.constructor == a;
obj.__proto__ == a.prototype;
我能想到的另一个实际差异:
var o = {
a : 1,
b : this.a + 2
};
在这种情况下,b将是未定义的,给出错误或归因于现在引用的this.a
。除了它之外的一切都不会是1
。在使用构造函数方法的情况下,这将起作用......
function Math() {
this.a = 1;
this.b = this.a +2 ;
}
var m = new Math();
答案 3 :(得分:0)
如果你想在js中应用OOP,那么使用protype比使用构造函数更好。因为js对象会将它的属性传递给它的孩子作为原型。
答案 4 :(得分:0)
函数构造函数创建一个新对象,你必须做三件额外的事情来吸收传统的类/继承设计:
ECMA6将引入新的语法,如extend和Class,但JS是一种原型语言。这只是意味着每次你创建一个对象var o = {};
它不是一个真正的空对象,它没有属性,而是坐在编译器的黑暗水域下面,存在一个称为原型的辅助对象,这里编译器链接回另一个对象。
当您要求编译器获取值时,例如console.log(this.x)
它首先查看对象拥有属性,如果它能找到它,它会装饰一个通气管并将其头部浸入温水中以搜索对象原型。如果它不在那里,编译器必须穿上它的湿衣服深入潜入黑暗的水域。如果编译器现在位于海床上,则它不再搜索,而是在最低级别的对象Object
上搜索。然后,编译器将咳嗽并且向后spl undefined
,因为它正在通过深渊再次呼吸它。
因此,您的属性和函数越接近对象的直接上下文,代码执行得越好。如果您尝试链接许多原型,编译器将在潜水和重新铺设之后获得弯曲。
在JS中创建类时,您将创建实例属性并设置原型:
var Cat = function() {
this.age = 3;
this.colour = 'black';
};
Cat.prototype.age = function() { console.log(this.age); };
使用new
关键字创建一个空白对象并将上下文设置为this
,因此在Cat
中我们只是增加当前上下文的属性,例如this.age = 3;
编译器已经知道Cat.prototype,这些函数链接到您的对象,而不是逐字复制到您的对象。
创建对象的new
方式很笨拙,以下内容包含原型委派;称之为mixins,扩展,继承或其他什么,重点是我们可以用其他对象扩充对象并将函数放在原型上,所以所有实例都可以看到它们。
var manufacturer = {
id:'manufacturer',
constructor : function (args) {
this.boss = args.boss || 'Bernie Ecclestone';
this.country = args.country || 'UK';
return this;
}
};
var vehicle = {
id:'vehicle',
constructor : function (args) {
this.colour = args.colour || 'blue';
this.wheels = args.wheels || 2;
extend.call(this, manufacturer, args);
return this;
}
};
var driver = {
id:'driver',
constructor : function (args) {
this.name = args.name || 'John';
return this;
},
info : function () { console.log(this.name); }
};
var engine = {
id:'engine',
constructor : function (args) {
this.type = args.type || 'V6';
this.fuel = args.fuel || 'petrol';
return this;
},
tune : function () {
this.type = 'super-charged';
this.fuel = 'ethanol';
console.log('Car now ' + this.type + ' with ' + this.fuel);
}
};
var car = {
id:'car',
constructor : function (args) {
extend.call(this, vehicle, args);
extend.call(this, driver, args);
extend.call(this, engine, args);
return this;
},
info : function () {
console.log('boss: ' + this.vehicle.manufacturer.boss);
console.log('country: ' + this.vehicle.manufacturer.country);
console.log('driver: ' + this.driver.name);
console.log('colour: ' + this.vehicle.colour);
console.log('wheels: ' + this.vehicle.wheels);
console.log('type: ' + this.engine.type);
console.log('fuel: ' + this.engine.fuel);
console.log('\n');
}
};
function extend(proto, args){
this[proto.id] = Object.create(proto);
proto.constructor.call(this[proto.id], args);
}
var ferrari = Object.create(car).constructor({
boss: 'Maurizio Arrivabene',
country:'Italy',
name: 'Steve',
colour: 'red',
wheels: 4,
type:'100cc',
fuel:'diesel'
});
var lotus = Object.create(car).constructor({
name: 'Jenson Button'
});
var mclaren = Object.create(car).constructor({
type:'hybrid',
fuel:'battery/petrol'
});
ferrari.engine.tune();
ferrari.info();
/*
Car now super-charged with ethanol
boss: Maurizio Arrivabene
country: Italy
driver: Steve
colour: red
wheels: 4
type: super-charged
fuel: ethanol
*/
lotus.info();
/*
boss: Bernie Ecclestone
country: UK
driver: Jenson Button
colour: blue
wheels: 2
type: V6
fuel: petrol
*/
mclaren.info();
/*
boss: Bernie Ecclestone
country: UK
driver: John
colour: blue
wheels: 2
type: hybrid
fuel: battery/petrol
*/