Phương thức tĩnh Object.create() tạo một đối tượng mới, sử dụng một đối tượng hiện có làm nguyên mẫu của đối tượng mới được tạo
Object.create(proto) Object.create(proto, propertiesObject)
proto
Đối tượng phải là nguyên mẫu của đối tượng mới được tạo
propertiesObject Tùy chọnNếu được chỉ định và không phải là // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 0, một đối tượng có vô số thuộc tính riêng chỉ định các bộ mô tả thuộc tính sẽ được thêm vào đối tượng mới được tạo, với các tên thuộc tính tương ứng. Các thuộc tính này tương ứng với đối số thứ hai của // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 1
Một đối tượng mới với các thuộc tính và đối tượng nguyên mẫu được chỉ định
// Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 2
Bị loại nếu proto không phải là // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 4 cũng không phải là // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 5
Dưới đây là một ví dụ về cách sử dụng Object.create() để đạt được sự kế thừa cổ điển. Đây là dành cho một kế thừa duy nhất, đó là tất cả những gì JavaScript hỗ trợ
// Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.'
Lưu ý rằng có những lưu ý cần chú ý khi sử dụng // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 7, chẳng hạn như thêm lại thuộc tính // Shape - superclass function Shape() { this.x = 0; this.y = 0; } // superclass method Shape.prototype.move = function (x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); // call super constructor. } // subclass extends superclass Rectangle.prototype = Object.create(Shape.prototype, { // If you don't set Rectangle.prototype.constructor to Rectangle, // it will take the prototype.constructor of Shape (parent). // To avoid that, we set the prototype.constructor to Rectangle (child). constructor: { value: Rectangle, enumerable: false, writable: true, configurable: true, }, }); const rect = new Rectangle(); console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true console.log("Is rect an instance of Shape?", rect instanceof Shape); // true rect.move(1, 1); // Logs 'Shape moved.' 8 để đảm bảo ngữ nghĩa phù hợp. Mặc dù Object.create() được cho là có hiệu suất tốt hơn so với việc biến đổi nguyên mẫu bằng o = {}; // Is equivalent to: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo is a regular data property foo: { writable: true, configurable: true, value: "hello", }, // bar is an accessor property bar: { configurable: false, get() { return 10; }, set(value) { console.log("Setting `o.bar` to", value); }, }, }); // Create a new object whose prototype is a new, empty // object and add a single property 'p', with value 42. o = Object.create({}, { p: { value: 42 } }); 0, nhưng sự khác biệt trên thực tế là không đáng kể nếu không có phiên bản nào được tạo và quyền truy cập thuộc tính chưa được tối ưu hóa. Trong mã hiện đại, cú pháp lớp nên được ưu tiên trong mọi trường hợp
Object.create() cho phép kiểm soát tinh chỉnh quá trình tạo đối tượng. Trên thực tế, cú pháp khởi tạo đối tượng là một đường cú pháp của Object.create(). Với Object.create(), chúng ta có thể tạo các đối tượng với một nguyên mẫu được chỉ định và một số thuộc tính. Lưu ý rằng tham số thứ hai ánh xạ các khóa tới bộ mô tả thuộc tính — điều này có nghĩa là bạn có thể kiểm soát khả năng đếm, khả năng cấu hình của từng thuộc tính, v.v. đồng thời, điều mà bạn không thể thực hiện trong trình khởi tạo đối tượng
o = {}; // Is equivalent to: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo is a regular data property foo: { writable: true, configurable: true, value: "hello", }, // bar is an accessor property bar: { configurable: false, get() { return 10; }, set(value) { console.log("Setting `o.bar` to", value); }, }, }); // Create a new object whose prototype is a new, empty // object and add a single property 'p', with value 42. o = Object.create({}, { p: { value: 42 } });
Với Object.create(), chúng ta có thể tạo một đối tượng. Cú pháp tương đương trong bộ khởi tạo đối tượng sẽ là chìa khóa
o = Object.create(null); // Is equivalent to: o = { __proto__: null };
Theo mặc định, các thuộc tính không thể ghi, đếm được hoặc có thể định cấu hình
o.p = 24; // throws in strict mode o.p; // 42 o.q = 12; for (const prop in o) { console.log(prop); } // 'q' delete o.p; // false; throws in strict mode
Để chỉ định một thuộc tính có cùng thuộc tính như trong trình khởi tạo, hãy chỉ định rõ ràng o = {}; // Is equivalent to: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo is a regular data property foo: { writable: true, configurable: true, value: "hello", }, // bar is an accessor property bar: { configurable: false, get() { return 10; }, set(value) { console.log("Setting `o.bar` to", value); }, }, }); // Create a new object whose prototype is a new, empty // object and add a single property 'p', with value 42. o = Object.create({}, { p: { value: 42 } }); 7, o = {}; // Is equivalent to: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo is a regular data property foo: { writable: true, configurable: true, value: "hello", }, // bar is an accessor property bar: { configurable: false, get() { return 10; }, set(value) { console.log("Setting `o.bar` to", value); }, }, }); // Create a new object whose prototype is a new, empty // object and add a single property 'p', with value 42. o = Object.create({}, { p: { value: 42 } }); 8 và o = {}; // Is equivalent to: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo is a regular data property foo: { writable: true, configurable: true, value: "hello", }, // bar is an accessor property bar: { configurable: false, get() { return 10; }, set(value) { console.log("Setting `o.bar` to", value); }, }, }); // Create a new object whose prototype is a new, empty // object and add a single property 'p', with value 42. o = Object.create({}, { p: { value: 42 } }); 9
o2 = Object.create( {}, { p: { value: 42, writable: true, enumerable: true, configurable: true, }, }, ); // This is not equivalent to: // o2 = Object.create({ p: 42 }) // which will create an object with prototype { p: 42 }
Bạn có thể sử dụng Object.create() để bắt chước hành vi của toán tử o = Object.create(null); // Is equivalent to: o = { __proto__: null }; 1
function Constructor() {} o = new Constructor(); // Is equivalent to: o = Object.create(Constructor.prototype);
Tất nhiên, nếu có mã khởi tạo thực sự trong hàm o = Object.create(null); // Is equivalent to: o = { __proto__: null }; 2, thì phương thức Object.create() không thể phản ánh nó