本文总结JavaScript中创建对象的三种主要方式:对象直接量、new关键字及Object.create()。重点解析Object.create()原型继承机制,包括参数为null或Object.prototype时的差异,以及原型链断裂对基本方法访问的影响,帮助开发者根据场景选择合适方案。
JavaScript 创建对象概述
JavaScript中创建对象主要有三种常用方法,本文将对这几种方式进行汇总说明。
对象直接量创建法
1. 对象直接量
所谓对象直接量,可以将其视为一种键值映射表。这是最直观且个人较为推荐的方式。
//创建简单对象
var obj1 = {}; //空对象
var obj2 = {
name: "ys",
age: 12
};
//创建复杂对象
var obj3 = {
name: "ys",
age: 12,
like: {
drink: "water",
eat: "food"
}
};
console.log(typeof obj1); //object
console.log(typeof obj2); //object
console.log(typeof obj3); //object
部分开发者可能会注意到,示例中的键名并未使用引号。确实,单引号或双引号在JavaScript中均可省略,但建议加上引号。原因在于加上引号后,键名可以包含空格、连字符或使用保留字等非常规命名。若键名规范,则不加引号亦可,具体视个人习惯而定。
var obj4 = {
"my name": "ys", //键值名中间有空格
"my-age": 12, //键值名中间有连字符
"while": 111 //键值名是关键字
}
console.log(obj4['my name']); //ys
console.log(obj4['my-age']); //12
console.log(obj4.while); //111
console.log(typeof obj3); //object
通过上述示例,可以清晰看出使用点号(.)与方括号([])访问对象属性的区别。
使用对象直接量创建对象时,键值对的值支持表达式运算,例如:
var obj3 = {
name: "ys",
age: obj2.age, //引用obj2.age
like: {
drink: "water",
eat: "food"
}
};
console.log(obj3.age); //100
使用 new 关键字创建
2. 使用 new 关键字创建对象
1)系统内置对象
var obj1 = new Object();
var obj2 = new Array();
var obj3 = new Date();
var obj4 = new RegExp("ys");
console.log(typeof obj1); //object
console.log(typeof obj2); //object
console.log(typeof obj3); //object
console.log(typeof obj4); //object
2)自定义对象
function Person(name, age){
this.name = name;
this.age = age;
}
var obj1 = new Person("ys", 12);
console.log(Object.prototype.toString.call(obj1)); //object
console.log(Person instanceof Object); //true
console.log(typeof obj1); //object
console.log(obj1.age); //12
Object.create() 原型继承详解
3. 使用 Object.create() 方法创建
该方法接收两个参数,此处主要解释第一个参数,第二个参数用于进一步描述对象属性,使用频率较低。第一个参数用于传入要继承的原型(prototype)对象。如何理解这一概念?
var obj1 = Object.create({
name: "ys",
age: 12
});
console.log(obj1); //{}
console.log(obj1.age); //12
例如 obj1 本身是一个空对象 {},为何能访问到属性值?我们需要理解第一个参数的含义:“传入要继承的原型对象”。
console.log(obj1.__proto__); //Object {name: "ys", age: 12}
虽然对象本身为空,但其原型链上存在数据(如 obj1.age),因此可以正常访问。
1)当第一个参数为 null 时
var obj2 = Object.create(null); //不继承对象应有的属性和方法
console.log(obj2 + "abc"); //报错 ,失去 + 功能
这会导致报错,正常参数生成的结构如下所示:

从图中可以看出,要继承的原型对象(即传入的参数)本身又继承了 Object 的原型对象。关键在于,Object 的原型对象包含了一些 JavaScript 对象的基本方法(如 indexOf()、toString()、'+' 运算符支持等)。如果传入 null,这条继承链就会断裂。
此时应能理解“JavaScript 中所有对象都继承自 Object,Object 处于继承链最顶端”这句话的含义。
2)创建空对象
var obj3 = Object.create(Object.prototype);
console.log(obj3); //{},(空对象,与前两个方法 {},new Object 相同)
console.log(obj3.__proto__); //如下图 ,只包含了基本对象的方法
相关代码结构如下:

这样创建的对象仅包含基本对象方法,不具备自定义属性。
3)参考以下代码,可更深入理解 Object.create() 方法,建议参考文章:《一种新的javascript对象创建方式Object.create()》。
var obj1 = {
name: "ys",
age: 12
};
obj1.prototype = {
sayName: function(){
return console.log(this.name);
}
};
/*①对象参数,只继承对象*/
var obj2 = Object.create(obj1);
console.log(obj2); //{}
console.log(obj2.name); //ys
/*console.log(obj2.sayName());*/ /* 报错 obj2.sayName is not a function*/
console.log(obj2.__proto__.prototype.sayName()); //ys 理解原型的原型
若仍不理解,可参考下图:

/*②对象原型,继承对象原型*/
var obj3 = Object.create(obj1.prototype);
console.log(obj3); //{}
console.log(obj3.name); //undefined,没有继承对象本身
obj3.name = "ys";
console.log(obj3.name); //ys
console.log(obj3.sayName()); //ys
代码执行后的结构(设置 name 后):

此时相信大家对第一个参数的作用已有清晰理解。
以上就是本文的全部内容,希望能帮助读者更好地掌握对象的创建方法。