JS学习快速笔记(七)

107 阅读2分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

面向对象(下)

上次我们说到JS该如何判断是this中的函数还是prototype中的函数。该__proto__出马了。

__proto__提供给JS一个链,即原型链。他是对象的独有属性。而他指向的是对象原型的prototype

function Person(name){
  this.name = name;
}
​
Person.prototype.say = function(){
  console.log("say Something..");
};
​
var personA = new Person("A");
​
console.log(personA.__proto__ === Person.prototype); //true

这样在personA这个实例中,就不只有constructorPerson产生联系,我们还有__proto__

那么在personA调用方法的时候,他会先去检查是不是自己的属性。

JS也提供了判断的方法hasOwnProperty()是否是自己的属性

personA.hasOwnProperty("say");//false

然后再通过__proto__获取Person.prototype检查是否有该属性。

Person.prototype.hasOwnProperty("say"); //true 

可能有同学会问,如果在Person.prototype中也没用这个属性呢?

前面提到__proto__就是提供原型链方法调用查询的。而__proto__是每个对象都独有的属性,所以Person.prototype他也是有__proto__属性。我们继续调用看看。

console.log(Person.prototype.__proto__);
/**
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, }
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()

*/

在浏览器中我们可以看到这么一大坨东西。这到底是什么呢?

我们在其中可以发现一个很熟悉的属性constructor

那么好,我们可以知道他是谁创建的了。

console.log(Person.prototype.__proto__.constructor);
//返回 ƒ Object() { [native code] }

答案很明细,他是Object创建的对象。而他就是Object.prototype

console.log(Person.prototype.__proto__ === Object.prototype ); // true

那么如果再继续呢?

console.log(Object.prototype.__proto__);// null

为空!那么当我们输入一个从personAObject都不存在的方法或者对象时,浏览器就会返回Uncaught TypeError或者undefined

这样我们脑海里应该有一条清晰的链

[personA] --(__proto__)--》 [Person.prototype] --(__proto__)--》 [Object.prototype] --(__proto__)--》 null

这就是原型链。

通过这么一条原型链,我们回头看personA.constructor的时候,我们可以发现,personA调用的constructor,其实是Person.prototype中的constructor

console.log(personA.constructor === Person.prototype.constructor);//true 

那么其实任何一个prototype对象都有一个constructor属性,指向它的构造函数。

面向对象总结

我们可以理解到在JS中主要就是由三个属性帮助我们构建面向对象。

  • constructor
  • prototype
  • __proto__

我们的总结也可以分成三条

  • 当我们创建对象或者想知道该对象被谁创建,使用constructor构造函数。
  • 当我们需要挂载一个统一的方法或者属性,我们使用prototype挂载方法或者属性。他是函数独有的,而我们的函数也恰好是对象。
  • 当我们搜索属性或者方法的时候,调用__proto__,他是对象独有的。

根据上面的三条。

我们按照personA的案例可以画出一个比较清晰的图...