8月得进步(一):浅谈原型对象和原型链🐻| 8月更文挑战

154 阅读4分钟

bgc-03.jpeg

8月得进步(一):浅谈原型对象和原型链🐻| 8月更文挑战

原型对象原型链是javascript中的非常重要的知识点,不仅是面试考官的划重点,我们同样都要学习清楚并弄懂

接下来仅仅是我重新温故后的个人看法,今后的实践运用中,希望自己还可以有更高层次的看法

原型对象

什么是原型对象?带着问题,我们来看看下面这个拓展


首先先来一段简单的构造函数,并实例化它
function Person (uname, age) {
			this.uname = uname;
			this.age = age;

			this.sing = function () {
				console.log('唱歌');
			}
		}
                
                let o1 = new Person('张三', 23);
		console.log(o1);

		let o2 = new Person('李四', 22);
		console.log(o2);

首先,我们这是一个构造函数的模板,里面有unameage的属性,还有sing的方法 然后我们实例化了o1,o2两个对象,这两个对象,我们都会有unameagesing。但是这个sing方法,我们每次new一个对象,我们都会重新开辟一块空间,用来存这个函数,这个函数是一模一样的,就会很浪费内存空间,所以,我们就把这个sing的方法存到原型对象上。

prototype

所以这里,我们说原型对象---就是构造函数(函数)的一个属性,任何一个函数都有。这个属性我们叫做prototype。并且,这个属性prototype是一个对象。

上面我们这样去写会更规范

function Person(uname, age) {
        this.uname = uname;
        this.age = age;

      }
Person.prototype.sing = function () {
       console.log("唱歌");
};
  • 构造函数的prototype属性指向了一个对象,我们把这个对象称为原型对象或者原型
  • 每一个构造函数都有这个属性
  • 当实例对象找不到成员的时候就会找原型对象上的成员

这个时候,我们来总结一下,因为浪费内存的原因,我们把sing放在原型对象上,所有实例化出来的对象上都会有这个方法,大大的节省了内存空间,总的来说就是共享方法,节省内存。所以,原型对象中的所有属性和方法都可以被构造函数的实例化对象继承

但是我们需要知道,方法也可以放到构造函数上,原型对象上也可以放方法

constructor

function Person () {}
console.log( Person.prototype );

image.png

我们看到Person构造函数的原型对象上有一个constructor属性,这个属性,用于指回构造函数本身。

console.log(Person.prototype.constructor);

输出结果为image.png,果然指回了构造函数本身

__proto __

这里,我们先介绍下,每一个对象都有__proto __这个属性,它是一个非标准的属性,w3c还未认可它,但是,这个属性是存在的。__proto __的作用是指回原型对象(prototype)。

我们还是用上面的例子

function Person (uname, age) {
			this.uname = uname;
			this.age = age;
		}
Person.prototype.sing = function () {
			console.log('唱歌')
		} 
let obj = new Person('王五', 22); 
console.log(obj.__proto__ === Person.prototype);// true

所以说,实例对象的__proto __指向了原型对象,证明了我们的结果。

并且这里,我们可以把__proto __称为对象原型(比较绕口,可以忽略不计),又叫隐式原型,prototype称为显示原型。

构造函数,实例,原型对象三者有什么关系呢

image.png 构造函数,是用来实例化对象的,而每个构造函数都有一个原型对象,我们可以把一些共同的方法,存在原型对象上,实例对象本身可能是没有这些方法,但是它却可以用这些方法,为什么呢?就是因为实例对象上找不到这些成员,它会沿着__proto __的指向去原型对象上找这些成员,原型对象,为了去记录它是属于哪一个构造函数的,又可以通过constructor指回构造函数本身。

那么,再次提问,原型对象有啥用???

原型对象对应的构造函数的实例方法或属性不存在时会去查找原型对象,结合构造函数原型的特征,实际开发中往往会将封装的功能函数添加到原型对象中

原型链

说起原型链我们很容易想起作用域链,这二者很相似,这里我们还是用画图的方法来描述一下什么是原型链

image.png

原型链:由原型构成链状的结果 原型对象是对象嘛?是!那么每一个对象都有__proto __,这个指针又指向了上一层的原型对象,是存在的

console.log(obj.__proto__.__proto__)

image.png

原型对象往上指,依然还有原型对象,这个原型对象又是构造函数的一个属性,我们再次可以用constructor指回是哪一个构造函数的。

console.log(obj.__proto__.__proto__.constructor)

image.png 指回了内置的Object函数,那么就是内置Object构造函数的原型对象

直到找到null也没找到,这样子连接成的链状结构就是原型链。当然,它很简易。

日记

希望明天的你会感激今天努力的自己!