1、对象的创建
// 字面量方法
let a = {name:1}
let a = new Object({name:1})
// 构造函数方法
let M = function(){this.name=1}
let a = new M()
// Object.creat方法
let P = {name:1}
let a = Object.create(P)
2、原型、原型链、实例、构造函数的关系
微信图片_20220303171118.pnglet M = function(){}
let a = new M()
prototype 表示原型对象,是区别于构造函数本身的另一个堆内存。
__proto__ 指向父级构造函数的原型对象,一直向上查找形成原型链。
每个函数对象都有prototype属性(原型对象),非函数对象没有prototype属性。
所有对象都有__proto__属性(包括函数)。
Object.prototype是整个原型链的顶端。
原型对象存在的原因:实例会继承构造函数和原型对象的方法和属性,但是如果这些方法和属性写在构造函数内,每一次创建都会在实例内部生成这些属性和方法,这样会占用过多内存,原型对象的属性是共有属性,创建时不会占用内存,而且通过原型链也可以访问这些属性和方法。而且可以通过M.prototype/Function.prototype/Object.prototype动态添加自定义的属性或者方法。
如果一个属性在当前对象找不到,js引擎会通过proto在原型链上向上查找,直到Object.prototype,还找不到就返回undefined。
prototype原型对象中的constructor构造器指向当前函数
M.prototype.constructor === M // true
Function.prototype位于所有函数的原型链上,Function.prototype又通过__proto__指向Object.prototype,所以所有的函数既是Function的实例又是Object的实例。
Function.prototype._proto_ === Object.prototype // true
实例的proto属性指向构造函数的原型对象
a.__proto__===M.prototype // true
一个有趣的现象,详细分析见 https://www.cnblogs.com/shuiyi/p/5343399.html
Function instanceof Object; //true
Object instanceof Function; //true
3、instanceof的原理
微信图片_20220303173757.pnga instanceof M // true
a instanceof Object // true
//instanceof运算时,通过判断a的原型链上是否存在Object.prototype
a.__proto__.__proto__ ..... === Object.prototype ?
//如果存在返回true 否则返回false
严格判断对象是哪个构造函数的实例(通过原型对象的constructor)
a.__proto__.constructor === M // true
a.__proto__.constructor === Object // false
4、new运算符
第一步:创建一个新对象,它继承自M.prototype
第二步:构造函数M被执行,参数/方法传入,同时上下文(this)被指向到这个新的对象实例。
第三步:如果构造函数返回一个新“对象”,那这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为第一步创建出来的对象。
// 模拟new运算符
let myNew = function(func){
let o = Object.create(func.prototype);
let k = func.call(o);
if(typeof k === 'object'){
return k;
}else{
return o;
}
}
let a2 = myNew(M);
a2 instanceof M; // true
网友评论