欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

原型与原型链

程序员文章站 2022-06-12 21:42:48
...

一.概念

  • javascipt中许多的对象。对象之中,分为普通对象函数对象,Object和Function则是JS自带的函数对象,而值类型则是普通对象。

值类型(string,number,boolean,undefined)

  • 对象内的一切都是属性,只有属性,没有方法。因为方法也只是一种属性,而且js中的属性可以进行扩展

  • 对象都是通过函数创建的。举个例子:

function Person(){
    this.name = "Leo";
    this.age = "25";
}
var p1 = new Person();//p1即为构造函数Person()的实例化对象

var arr = [10,20,30,40,50,60]//这种语法糖形式的对象创建,是由Array()函数创建简化而来的。

这个过程种,系统做了什么?

var p1 = {};
p1.__proto__ = Person.prototype;
Person.call(p1);//初始化p1

//这个结论是可以通过p1.__proto__ === Person.prototype反推的
  • 那么__proto__和prototype是什么?
__proto__(隐式原型) :每创建一个对象都会在其内部初始化一个__proto__属性,当我们访问一个对象的属性的时候,如果对象内部不穿在这个属性,系统就会去__proto__中寻找,这个__proto__作为一个对象,又会有自己的__proto__,直到null。这就是我们所说的原型链概念

prototype(显式原型) :每创建一个函数,就会同时在内存中分配得创建一个prototype对象。默认的只有一个constructor的属性指向构造函数本身。

二.举例

function Person(){
    this.name = "Tom";
}
Person.prototype = {
	constructor:Person,//避免重写时丢失导致指向Object函数
    sayName:function(){
        console.log("My name is ",this.name)
    }
}
var p = new Person();
console.log(Person);//不包含sayName()方法
console.log(p);//sayName()方法可以从__proto__中获取到
p.sayName();//输出My name is  Tom

console.log(p.__proto__.constructor);//结果等同于输出Person
Function.prototype.a = "a";
Object.prototype.b = "b";
function Person(){};
console.log(Person);//function Person()
let p = new Person();
console.log(p);//Person Object
console.log(p.a);//undefined
console.log(p.b);//b

三.结论

查找属性,如果本身没有,则会去__proto__中查找,也就是构造函数的显式原型中查找,如果构造函数中也没有该属性,因为构造函数也是对象,也有__proto__,那么会去它的显式原型中查找,一直到null,如果没有则返回undefined。

那么问题来了,prototype派不上用场吗?

恰恰相反

四.应用

  1. 使用原型对象拓展自定义属性
Person.prototype.email = "[email protected]";
  1. 拓展数组类的功能
var arr=[10,20,30,40,50,60];
Array.prototype.sayWhere = function(num){
	for (var i = this.length - 1; i >= 0; i--) {
		if (this[i] == num) {
			return i;
		}
	}
	return -1;
}
console.log(arr.sayWhere(20));
  1. 同第二条应用,拓展自定义的构造函数的功能,同时不影响在其他范围内对该构造函数的影响。