- 原型
我们会发现,如果想更改构造器函数里的属性和方法,只能在构造器函数里面改,它不能像对象一样,直接以点的形式添加,比如:
Person.study = “JavaScript”,这样是不允许的。
JavaScript构造器函数其实就是一个函数,函数有一个属性:prototype,也就是原型。
构造器函数可以通过prototype添加属性和方法。比如:
<p id="demoa"></p>
<p id="demob"></p>
<script>
// Person 对象的构造器函数
function Person(name, age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.showme = function(){
return "我叫" + this.name + '年龄' + this.age;
}
}
Person.prototype.study = 'JavaScript';
Person.prototype.showSex = function(){return this.sex};
// 创建 Person 对象
var a = new Person('小明',18,'男');
document.getElementById("demoa").innerHTML = a.study; //JavaScript
var b = new Person("小红",16,"女");
document.getElementById("demob").innerHTML = b.showSex(); //女
</script>
对于对象原型的修改,我们只允许修改自己的对象原型,绝不要修改标准 JavaScript对象的原型。
- 原型继承
继承就是字面意思,像我们从父母那里继承一样,JavaScript对象是从对象构造器函数里的原型继承属性和方法的。也就是说,JavaScript自己写的对象构造器函数都是通过prototype这个属性来添加属性和方法的。
对象可以看成对象构造器的一个孩子。孩子当然可以从父母那里继承基因或者财产了。
每一个对象都有一个__proto__
属性。大家可以在浏览器的调试模式下随便打印一个数据类型变量就可以看到。比如:
__proto__
属性是用来指向对象的构造器函数的prototype
。从上图,我们可以看出,变量a的构造器函数是Number,它里面的方法都是通过prototype添加上的。
细心的同学可能会发现,这个Number构造器里面也有一个__proto__
,哈哈。
我们要知道,我们是爸爸的孩子,其实,爸爸也是一个孩子,爸爸是爷爷的孩子。Number的__proto__
属性指向的是Object。也就是说,Number是由Object构造器生成的。点开Number的__proto__
属性,我们来看一下:
我们可以看到Object构造器函数里的方法和属性。如果细心一点,我们会发现Object构造器里,没有__proto__
属性,为什么呢?因为对象构造器是顶端了,它是鼻祖了。
上面对象a不仅可以拥有Number里的属性和方法,Object里的属性和方法也同样会继承。
不仅仅是数值类型,字符串、布尔值、数组等等,我们学到的所有的数据类型,通过
__proto__
属性往上找,最终都会找到Object。这也就解释了,为什么一直说,JS里所有的内容都可以看成是对象。
当我们访问一个对象里的属性和方法时,如果对象本身没有该属性和方法,程序会去它的构造函数里的prototype属性里去找,如果它构造函数里的prototype属性里也没有,会继续向上找,直到找到Object的prototype属性里,如果还没有,就会返回undefined。这就是所谓的原型链。
给大家做了一张图:
希望图片能让大家清晰的明白它们之间的关系。如果想看更多关于前端知识的文章,欢迎大家微信搜索公众号:“刘小妞的栖息地”或者识别下图的二维码查看,感谢大家的支持,有讲的不好的地方请多指正。