一遍带你了解js中的new以及原形链

181 阅读2分钟

new运算符:

  • 在内存中创建一个新对象
  • 新对象内部的prototype特性被赋值为构造函数的prototype属性
  • 构造函数内部的this被赋值为这个新对象(即this指向新对象)
  • 执行构造函数内部的代码(即给新对象添加属性)
  • 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象
function animal(name) {
  this.name = name;
  console.log(this);
  return name;
}

var dog = new animal("旺财");
var cat = animal("阿喵");

console.log(dog);
console.log(cat);
console.log(dog.name);
console.log(cat.name);

输出如下: QQ截图20211117120523.png

原形和原形链:

  • 每一个构造函数都拥有一个 prototype 属性,这个属性指向一个对象,也就是原型对象
  • 原型对象默认拥有一个 constructor 属性,指向指向它的那个构造函数
  • 每个对象都拥有一个隐藏的属性 __proto__,指向它的原型对象
  • 实例可以共享原型上面的属性和方法
  • 实例自身的属性会屏蔽原型上面的同名属性,实例上面没有的属性会去原型上面找
function Person() {}
class an {}
Person.prototype.name = "小丫";
var p1 = new Person();
p1.sex = "女";
p1.name = "小花";
console.log(p1);
console.log(p1.__proto__.name);
console.log(Person.prototype);
console.log(Person.__proto__);
console.log(p1.prototype);
console.log(Person);
console.log(an);
console.log(an.prototype);
console.log(an.__proto__);

QQ截图20211117122051.png

总结:

构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写,构造函数和普通函数的区别在于:调用方式不一样。作用也不一样(构造函数用来新建实例对象);

给构造函数原形上添加的属性,使用hasOwnProperty判断构造函数的实例上是否有该属性,结果会为false;

hasOwnProperty只能查找对象自身拥有的属性,不能查找原形链上的属性;

for in 可以查找到对象自身的属性以及原形链上的属性,利用for in夹hasOwnProperty可以查找出对象的自身属性;

对象obj的原形上有name,给对象添加一个自身属性name,obj只可以调用自身属性的name,obj.proto.name调用原形上的name,原形上的name不会应为对象自身属性的的添加而被覆盖掉;

构造函数实例没有proto但是没有prototype,构造函数同时拥有prototype和proto,class类也同时拥有prototype和proto,在不自己实现继承的情况下class类和函数拥有相同的proto