js原型链/instanceof原理/new运算符

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.png
let 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.png
a 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

你可能感兴趣的:(js原型链/instanceof原理/new运算符)