用 JavaScript 创建对象的最佳方式是什么? 在对象属性之前有必要使用‘ var’吗?

到目前为止,我看到了用 JavaScript 创建对象的三种方法。创建对象的最佳方式是什么? 为什么?

我还看到在所有这些示例中,在属性之前都没有使用关键字 varーー为什么?是否有必要在属性名称之前声明 var,因为它提到属性是变量?

在第二种和第三种方式中,对象的名称是大写,而在第一种方式中,对象的名称是小写。我们应该使用什么样的情况作为对象名称?

第一种方法:

function person(fname, lname, age, eyecolor){
this.firstname = fname;
this.lastname = lname;
this.age = age;
this.eyecolor = eyecolor;
}


myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");

第二种方法:

var Robot = {
metal: "Titanium",
killAllHumans: function(){
alert("Exterminate!");
}
};


Robot.killAllHumans();

第三种方法ーー使用数组语法的 JavaScript 对象:

var NewObject = {};


NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }
171038 次浏览

没有 最好的的方式,它取决于您的用例。

  • 如果要创建几个类似的对象,请使用 方法1。在您的示例中,Person(您应该以大写字母开头的名称)称为 构造函数构造函数。这与其他面向对象语言中的 课程类似。
  • 如果您只需要某种类型的 一件物品(如单件) ,则使用 方法2。如果希望从另一个对象继承这个对象,那么必须使用构造函数。
  • 如果要根据对象的其他属性初始化对象的属性,或者具有动态属性名,请使用 方法3

更新: 按照第三种方法的要求示例。

附属物业:

以下内容不起作用,因为 this指的是 没有指的是 book。无法使用对象文本中的其他属性值初始化属性:

var book = {
price: somePrice * discount,
pages: 500,
pricePerPage: this.price / this.pages
};

相反,你可以这样做:

var book = {
price: somePrice * discount,
pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;

动态属性名称:

如果属性名存储在某个变量中或通过某个表达式创建,则必须使用括号表示法:

var name = 'propertyName';


// the property will be `name`, not `propertyName`
var obj = {
name: 42
};


// same here
obj.name = 42;


// this works, it will set `propertyName`
obj[name] = 42;

没有创建对象的“最佳方式”,每种方式都有其优点,这取决于你的用例。

构造函数模式(与 new操作符配对以调用它的函数)提供了使用原型继承的可能性,而其他方法则没有。因此,如果您想要原型继承,那么构造函数是一个很好的方法。

但是,如果希望使用原型继承,也可以使用 Object.create,这使得继承更加明显。

如果在创建时恰好拥有所有希望设置的属性,那么创建一个对象文本(ex: var obj = {foo: "bar"};)非常有用。

对于以后设置属性,如果您知道属性名称,则 NewObject.property1语法通常优于 NewObject['property1']。但是后者在实际上没有提前获得属性名时非常有用(例如: NewObject[someStringVar])。

希望这个能帮上忙!

我想这取决于你想要什么。对于简单的对象,我想您可以使用第二种方法。当您的对象变得更大并且计划使用类似的对象时,我想第一种方法会更好。这样,您还可以使用原型来扩展它。

例如:

function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getCircumference = function() {
return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
return Math.PI * this.radius * this.radius;
}

我不太喜欢第三种方法,但是它对于动态编辑属性(例如 var foo='bar'; var bar = someObject[foo];)非常有用。

定义函数的方法有很多种。这完全是根据你的要求。下面是一些风格:-

  1. 对象构造函数
  2. 文字构造函数
  3. 基于功能
  4. 基于原型
  5. 基于函数和原型
  6. 基于单件模式

例子:

  1. 对象构造函数
var person = new Object();


person.name = "Anand",
person.getName = function(){
return this.name ;
};
  1. 文字构造函数
var person = {
name : "Anand",
getName : function (){
return this.name
}
}
  1. 函数构造函数
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}
  1. 原型机
function Person(){};


Person.prototype.name = "Anand";
  1. 功能/原型组合
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name
}
  1. 辛格尔顿
var person = new function(){
this.name = "Anand"
}

您可以在控制台上尝试它,如果您有任何困惑。

有许多方法可以用 JavaScript 创建对象。 在 JavaScript 中,使用构造函数创建对象或对象文本表示法的方法很多。同时创建一个 Object 实例,然后向其中添加属性和方法,在 JavaScript 中创建对象有三种常见的方法。

构造函数

有一些内置的构造函数,我们可以时不时地使用它们,比如 Date () ,Number () ,Boolean ()等,所有的构造函数都以大写字母开头,同时我们可以在 JavaScript 中创建自定义的构造函数,如下所示:

function Box (Width, Height, fill) {
this.width = Width;  // The width of the box
this.height = Height;  // The height of the box
this.fill = true;  // Is it filled or not?
}

您可以调用它,只需使用 new ()来创建构造函数的一个新实例,创建类似下面这样的东西,并使用填充参数调用构造函数:

var newBox = new Box(8, 12, true);

对象文字

在 JavaScript 中,使用对象文字是非常常用的创建对象的例子,这是一个创建简单对象的例子,你可以为你的对象属性赋予任何东西,只要它们被定义:

var person = {
name: "Alireza",
surname: "Dezfoolian"
nose: 1,
feet: 2,
hands: 2,
cash: null
};

原型机

在创建一个对象之后,你可以将更多的成员原型化,例如为我们的 Box 添加颜色,我们可以这样做:

Box.prototype.colour = 'red';

当然有一个最好的方法。 javascript 中的对象具有可枚举和不可枚举的属性。

var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]

在上面的示例中,您可以看到一个空对象实际上具有属性。

好的,首先让我们看看哪种方法最好:

var new_object = Object.create(null)


new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc


console.log("toString" in new_object) //=> false

在上面的例子中,日志将输出 false。

现在让我们看看为什么其他对象创建方法是不正确的。

//Object constructor
var object = new Object();


console.log("toString" in object); //=> true


//Literal constructor
var person = {
name : "Anand",
getName : function (){
return this.name
}
}


console.log("toString" in person); //=> true


//function Constructor
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}


var person = new Person ('landi')


console.log("toString" in person); //=> true


//Prototype
function Person(){};


Person.prototype.name = "Anand";


console.log("toString" in person); //=> true


//Function/Prototype combination
function Person2(name){
this.name = name;
}


Person2.prototype.getName = function(){
return this.name
}


var person2 = new Person2('Roland')


console.log("toString" in person2) //=> true

如上所示,所有示例都为 true。这意味着如果你有一个案例,你有一个 for in循环,看看对象是否有一个属性将导致你错误的结果可能。

请注意,最好的方法是不容易的。必须逐行定义对象的所有属性。其他方法更简单,创建对象的代码也更少,但在某些情况下必须注意。 我总是使用“其他方式”的方式,如果你不使用上述警告的最佳方式,一个解决方案是:

 for (var property in new_object) {
if (new_object.hasOwnProperty(property)) {
// ... this is an own property
}
}

主要有三种创建对象的方法-

最简单的方法是使用 对象文字

const myObject = {}

虽然这个方法是最简单的,但是有一个缺点,即如果你的对象有行为(函数在其中) ,那么将来如果你想对它做任何改变,你就必须在所有的对象 中改变它。

所以在这种情况下,最好使用工厂函数或构造函数

工厂函数 是那些返回 object.e.g-的函数

function factoryFunc(exampleValue){
return{
exampleProperty: exampleValue
}
}

构造函数 是那些使用“ this”keyword.e.g-为对象分配属性的函数

function constructorFunc(exampleValue){
this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);

虽然很多人说对象创建没有最好的方法,但是到2019年为止,为什么有这么多的方法可以在 JavaScript 中创建对象,这是有道理的,这与 JavaScript 在1997年 EcmaScript 发布的不同迭代中的进步有关。

在 ECMAScript 5之前,只有两种创建对象的方法: 构造函数或文字表示法(一种替代 new Object ()的更好方法)。使用构造函数符号可以创建一个可以实例化为多个实例的对象(使用 new 关键字) ,而文字符号只提供一个对象,比如单例对象。

// constructor function
function Person() {};


// literal notation
var Person = {};

不管你使用什么方法,JavaScript 对象只是键值对的属性:

// Method 1: dot notation
obj.firstName = 'Bob';


// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';


// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
value: 'Bob',
writable: true,
configurable: true,
enumerable: false
})


// Method 4: Object.defineProperties
Object.defineProperties(obj, {
firstName: {
value: 'Bob',
writable: true
},
lastName: {
value: 'Smith',
writable: false
}
});

在 JavaScript 的早期版本中,模拟基于类的继承的唯一真正方法是使用构造函数。构造函数是用‘ new’关键字调用的特殊函数。按照惯例,函数标识符是大写的,但不是必需的。在构造函数内部,我们引用‘ this’关键字为构造函数隐式创建的对象添加属性。构造函数隐式地将具有填充属性的新对象返回给调用函数,除非显式地使用 return 关键字并返回其他内容。

function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;


this.sayName = function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}


var bob = new Person("Bob", "Smith");
bob instanceOf Person // true

SayName 方法有一个问题。通常,在面向对象的类别基础编程语言中,您使用类作为工厂来创建对象。每个对象都有自己的实例变量,但是它有一个指向类蓝图中定义的方法的指针。不幸的是,当使用 JavaScript 的构造函数时,每次调用它时,它都会在新创建的对象上定义一个新的 SayName 属性。因此,每个对象都将有自己的惟一 SayName 属性。这将消耗更多的内存资源。

除了增加内存资源之外,在构造函数内定义方法还消除了继承的可能性。同样,该方法将被定义为新创建对象上的一个属性,而不是其他对象,因此继承不能像。因此,JavaScript 提供了原型链作为一种继承形式,使 JavaScript 成为一种原型语言。

如果父类和父类共享子类的许多属性,那么子类应该继承这些属性。在 ES5之前,它完成了以下工作:

function Parent(eyeColor, hairColor) {
this.eyeColor = eyeColor;
this.hairColor = hairColor;
}


Parent.prototype.getEyeColor = function() {
console.log('has ' + this.eyeColor);
}


Parent.prototype.getHairColor = function() {
console.log('has ' + this.hairColor);
}


function Child(firstName, lastName) {
Parent.call(this, arguments[2], arguments[3]);
this.firstName = firstName;
this.lastName = lastName;
}


Child.prototype = Parent.prototype;


var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair

我们使用上述原型链的方式有一个怪异之处。由于原型是一个活动链接,通过更改原型链中一个对象的属性,您也将更改另一个对象的相同属性。显然,更改子方法的继承方法不应更改父方法。Create 通过使用一个 polyfill 解决了这个问题。因此,使用 Object.create,您可以安全地修改原型链中子属性,而不会影响原型链中父属性的相同属性。

ECMAScript 5引入 Object.create 来解决上述构造函数中用于对象创建的 bug。Create ()方法 CREATES 一个新对象,使用一个现有对象作为新创建对象的原型。由于创建了一个新对象,因此不再存在修改原型链中的子属性将修改父对象对链中该属性的引用的问题。

var bobSmith = {
firstName: "Bob",
lastName: "Smith",
sayName: function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}


var janeSmith = Object.create(bobSmith, {
firstName : {  value: "Jane" }
})


console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.

在 ES6之前,使用函数构造函数和 Object.create 有一个常见的创建型模式:

const View = function(element){
this.element = element;
}


View.prototype = {
getElement: function(){
this.element
}
}


const SubView = function(element){
View.call(this, element);
}


SubView.prototype = Object.create(View.prototype);

现在 Object.create 和构造函数已经被广泛用于 JavaScript 中的对象创建和继承。然而,ES6引入了类的概念,它主要是 JavaScript 现有的基于原型的继承的语法糖。类语法没有向 JavaScript 引入新的面向对象继承模型。因此,JavaScript 仍然是一种原型语言。

ES6类使继承容易得多。我们不再需要手动复制父类的原型函数并重置子类的构造函数。

// create parent class
class Person {
constructor (name) {
this.name = name;
}
}


// create child class and extend our parent class
class Boy extends Person {
constructor (name, color) {
// invoke our parent constructor function passing in any required parameters
super(name);


this.favoriteColor = color;
}
}


const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue

总之,JavaScript 中对象创建的这5种不同策略与 EcmaScript 标准的发展是一致的。