乐趣区

重新整理的一遍JS的原型链继承

前言

粗略记录一下,然后让大神看看顺便纠正?

内容

  • JS 的原型链相关
  • JS 继承(正在看中)

JS 的原型链相关

一、首先,JS 里几乎所有值都是对象(使用的时候)!

我们知道,JS 基础数据类型是 number,string,boolean,undefined 和 null,而引用类型就 object,
之前看的时候,我很奇怪为什么像 var str = “”;这个 str 明明的类型是 String,为什么它却可以引用 String.prototype 原型对象的属性和方法呢,并且它确实有对象才有的__proto__和 constructor 属性,

var str = '';console.log(str.__proto__ === String.prototype) //true

console.log(str.constructor === String) //true

console.log(str instanceof String); //false,前面两个都符合了,这个竟然是返回 false,不是 String 的实例

console.log(String.prototype.isPrototypeOf(str)); //false,跟 instanceof 功能是一样的

后面百度查了一下,原因是

读取字符串的时候会创建一个对象 ,但是这个对象只是 临时 的,所以我们称它为临时对象,学术名字叫包装对象,说它临时,是因为我们在读取它的属性的时候,js 会把这个 string 字符串通过 new String() 方式创建一个字符串对象,一旦引用结束,这个对象就被销毁了。

所以说就是像读取对象那样读取属性的时候,暗地里帮我 new String()了,不读取的时候,就是基础类型,所以判断是不是实例才返回了 false

str.name = 'nihao';  // 可以这样写不报错,因为暗地里帮我对象化了,str.name         // 可以点 name 出来,但是是 undefined, 没错

总结:目前发现除了 undefined 和 null 不能这样搞,其他类型都是有__proto__和 constructor 属性,所以说,JS 几乎所有值都为对象

二、__proto__,prototype, 和 constructor 关系

首先,要明确两点的是

  • 函数才有 prototype 属性,这个属性指向的那个对象我们一般也叫做原型对象
  • 对象才有__proto__和 constructor 属性,那函数有没有?肯定有啊,函数本来就是属于引用数据类型的一种,就是 Object

    • __proto__属性,指向构造函数的原型对象,也就是函数.prototype
    • constructor 属性,指向构造函数,但是有一个值的 constructor 是特殊的,就是 函数.prototype.constructor, 原型对象的 constructor 属性指回构造函数(?????又说特殊,不是还是指回构造函数吗,嗯,我下面会做解释)

好了,那明确这两点之后,再说说这三者有什么关系,先放图吧


先说一下这个,按照这个图的意思,有一个构造 Person 函数,这个函数默认就会有 prototype 属性,这个属性指向的值是一个对象,我们叫做原型对象,然后呢,Person.prototype 这个原型对象,是的,它是一个对象,所以,它也就有 constructor 属性(我上面的结论),这个属性默认指回构造函数,也就是 Person 函数,原型对象的 name,age 这些就是我们自己往这个对象加的,Person.prototype.name = ‘xxx’, 就像这样, 然后
两个实例,person1,person2 这两个对象,有__proto__属性对吧,它指向是构造函数的原型对象,就是 Person.prototype

// 构造函数 Person
function Person(){}
// 往原型对象加值
Person.prototype.name = 'mychirs';
Person.prototype.age = 29;
Person.prototype.job = 'Software Engineer';
Person.prototype.sayName = function(){alert(this.name);
};

// 两个实例
var person1 = new Person();
var person2 = new Person();

console.log(Person.prototype.constructor === Person)  //true
console.log(person1.__proto__ === Person.prototype)  //true
console.log(person2.__proto__ === Person.prototype)  //true

好了,说完上面那个图已经差不多了,再放多一张图

这个图补充了几个上面那张图没有的点,第一,原型链的尽头是 Object.prototype.__proto__, 值为 null;第二,函数的 constructor 指向的是 Function 这个构造函数(这个 Function 是 JS 内置的几个构造函数之一),然后 Function 的 constructor 还是指它自己,也就是 Function,如果你一直.constructor.constructor, 你会发现一直都是在指 Function注意这里的 constructor 和原型对象的 constructor 不同 ,如果按照 constructor 指向的是构造函数,那么函数.prototype.constructor 应该指向的是 Object 构造函数, 但事实就是不是的,原型对象的 constructor 指的就是原型对象的构造函数, 这里就证明我上面结论说的第二点,放下代码看看

// 构造函数 Person
function Person(){}

var obj = {}
var person1 = new Person()

console.log(Person.constructor === Function)  //true, 正常来说,constructor 指向的就是构造函数
console.log(Person.constructor.constructor.constructor  === Function)  //true, 一直点下去都是这样

console.log(Person.prototype.constructor === Object)  //false, 原型对象的 constructor 是特殊的,记住就好
console.log(Person.prototype.constructor === Person)  //true,这样才对
console.log(obj.constructor === Object)  //true
console.log(person1 .constructor === Person)  //true

console.log(obj.constructor.prototype.__proto__=== null)  //true,原型链尽头,null

JS 的继承

补充中。。。

参考链接:
挺好的原型对象说明文章
原型链说明文章

退出移动版