创建object对象主要有字面量创建、new和object.create()三种方式
一、字面量创建
var objA = {};
objA.name = 'a';
objA.sayName = function() {
console.log(`My name is ${this.name} !`);
}
// var objA = {
// name: 'a',
// sayName: function() {
// console.log(`My name is ${this.name} !`);
// }
// }
objA.sayName();
console.log(objA.__proto__ === Object.prototype); // true
console.log(objA instanceof Object); // true
二、new
new创建的步骤:首先会内部创建一个object空对象,然后把object的隐式原型指向构造函数的显式原型,再借用call改变this的指向,执行构造函数,最后判断执行结果返回的类型,若是object类型,则new返回这个结果,若不是则返回空object对象。
function mynew(fn){
//创建新对象
var obj = {}
//obj隐式原型指向传入的fn的显式原型
obj.__proto__ = fn.prototype
//改变this指向,注意用call后面参数的处理
let result = fn.call(obj, Array.from(arguments).slice(1))
//判断返回结果
return result instanceof object ? result : obj
}
所以字面量创建和new创建的主要区别就是:new创建的效率没有字面量创建高,因为new内部多执行了代码。但他们最后创建的对象都是object的实例且objA.__proto__ === Object.prototype为true
三、object.create()
它会让新创建对象的隐式原型指向一个现有对象
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person); // me.__proto__ === person
me.name = "Matthew"; // name属性被设置在新对象me上,而不是现有对象person上
me.isHuman = true; // 继承的属性可以被重写
me.printIntroduction(); // My name is Matthew. Am I human? true
object.create(proto, [propertiesObject])
proto: 必传,是新创建对象的隐式原型
[propertiesObject]:可选,定义新创建对象里的一些属性和方法,注意:不是在隐式原型上定义 的,而是在新创建对象上定义的,可以用hasOwnProperty()访问到
注意:若proto为null,则新创建的对象是一个空对象,不会继承object.prototype上的属性和方法
var bb = Object.create(null, {
a: {
value: 2,
writable: true,
configurable: true
}
});
console.dir(bb); // {a: 2}
console.log(bb.__proto__); // undefined
console.log(bb.__proto__ === Object.prototype); // false
console.log(bb instanceof Object); // false 没有继承`Object.prototype`上的任何属性和方法,所以原型链上不会出现Object
// ----------------------------------------------------------
var cc = Object.create({b: 1}, {
a: {
value: 3,
writable: true,
configurable: true
}
});
console.log(cc); // {a: 3}
console.log(cc.hasOwnProperty('a'), cc.hasOwnProperty('b')); // true false 说明第二个参数设置的是新对象自身可枚举的属性
console.log(cc.__proto__); // {b: 1} 新对象cc的__proto__指向{b: 1}
console.log(cc.__proto__ === Object.prototype); // false
console.log(cc instanceof Object); // true cc是对象,原型链上肯定会出现Object
通过object.create()创建的对象它依然是object的实例(null除外)但cc.__proto__ === Object.prototype // false
手写object.create()
function create(F,property){
//内部新创建一个函数
var f = function() { }
//新创建函数的显式原型指向传入的对象,这样f实例的隐式原型会指向F
f.prototype = F
let result = new f()
//将传入的自定义属性复制
if(property){
Object.assign(result,property)
}
//输出f的实例
return result
}