JavaScript学习笔记——原型及原型链

原型

构造函数创建对象带来的问题
实例:

function Person(name, age){
	this.name = name
	this.age = age
	this.SayName = function(){
		console.log(this.name)
	}
}
var per1 = new Person('小白', 20 );
var per2 = new Person('小黑', 24);

此时会出现问题:

console.log(per1.SayName == per2.SayName)     // false

这样就会带来内存浪费的问题
解决的方法:可通过原型来解决
原型作用之一:数据共享,节省内存空间
如果:

var sayname = function SayName(){
 	console.log(this.name);
}
function Person(name, age){
	this.name = name
	this.age = age
	this.SayName = sayname;
}
var per1 = new Person('小白', 20 );
var per2 = new Person('小黑', 24);

此时会有:

console.log(per1.SayName == per2.SayName)     // true

通过原型来添加方法,解决数据共享,节省内存空间

Person.prototype.eat = function(){
	console.log('dinner!')
}
console.log(per1.eat == per2.eat)   // true

查看实例对象会有:
实例对象
实例对象中并没有eat方法,但仍能够使用

per1.eat()        // dinner!
console.log(per1.eat == per1.__proto__.eat)      // true

实例对象
实例对象中有__proto__这个属性,叫做原型,其也是一个对象,这个属性是给浏览器使用的,并不是标准的属性,__proto__也可叫做原型对象
构造函数中有prototype这个属性,叫做原型,也是一个对象,这个属性是给程序员使用的,是标准属性
注:
因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
实例对象的__proto__指向了构造函数的原型对象prototype

console.log(per1.__proto__ == Person.prototype)    // true

通过原型添加属性

Person.prototype.gender = 'male';

实例对象
构造函数、实例对象和原型对象之间的关系
构造函数可以实例化对象;
构造函数中有一个属性,叫做prototype,是构造函数的原型对象;
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数;
构造函数
实例对象的原型对象__proto__指向的是该构造函数的原型对象;
在这里插入图片描述
构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
利用原型共享数据
什么样子的数据需要写在原型中?
需要共享的数据就可用写在原型中
属性可以共享,方法也可以共享
而实例对象中的方法是可以相互访问的
实例:

// 构造函数
function Animal(name, age){
    this.name = name;
    this.age = age;
}
var dog = new Animal('MaoMao', 1)

图示有:
Dog

// 手动修改构造器的指向
Animal.prototype = {
    constructor: Animal,
    attribute: 'cute',
    play: function(){
        console.log('与主人玩耍!!!');
    },
    eat: function(){
        console.log('寻食');
        this.play();
    }
}
var dog = new Animal('MaoMao', 1)

dog
实例对象使用属性和方法层层的搜索
实例对象使用的属性或者方法,先在实例中查找,找到了则直接使用,找不到,就去实例对象的__proto__指向的原型对象prototype中找,找到则使用,找不到则报错

原型链

其是一种关系,实例对象与原型对象之间的关系是通过原型__proto__来联系的
原型链指向是否可以改变?

  • 构造函数中的this就是实例对象
  • 原型对象中的方法中的this就是实例对象
function Book(name){
	this.name = name;
	console.log(this);
}
Book.prototype.read = function(){
	console.log('读书!');
	console.log(this);
}

b1
dushu
试图改变原型的指向
实例:

console.log(b1.__proto__ == Book.prototype)         // true
console.log(b1.__proto__.__proto__ == Book.prototype.__proto__)      //true
console.log(Book.prototype.__proto__.__proto__)    // null

__proto__

function Magzine(){
	
}
Magzine.prototype.Browse = function(){
	console.log('翻阅杂志!');
}

magzine
此时有:
m1

// 试图改变原型的指定
Magzine.prototype = new Book('network');
var m2 = new Magzine();

m2.read();         //  读书!
m2.Browser();      //  报错

m2
m2proto
原型的指向是可以改变的
如果原型指向改变了,那么就应该在原型改变指向之后添加原型方法

原型最终指向了哪里?

  • 实例中有__proto__原型
  • 构造函数中有prototype原型

因为prototype是对象,所以prototype这个对象也有__proto__,那么它是指向哪里?
实例对象中的__proto__指向的是构造函数prototype
所以,prototype这个对象中的__proto__指向就应该是某个构造函数中的原型prototype

console.log(Book.prototype.__proto__)   

Book

console.log(Book.prototype.__proto__ == Object.prototype)       // true

实例对象中属性和原型对象中的属性的重名问题
实例对象中访问这个属性,应该先从实例对象中找,找到了就直接使用,找不到就去指向的原型对象中去找,找到了就使用
问题:如果找不到呢?
JS是一门动态类型的语言,对象没有的属性,点了,对象就有了这个属性,即对象.属性名字,该对象就有了这个属性,但是这个属性并没有被赋值,所以,结果为:undefined
b1age

Book.prototype.type = 'paper';
console.log(b1.type)          // paper

可以通过实例对象来改变原型对象中的属性值吗?
不能

b1.type = 'electronic';
console.log(b1.type)           // electronic
console.log(Book.prototype.type)         // paper

若想改变原型对象中的属性的值,可直接通过 原型对象.属性 = 值; 改变

Book.prototype.type = 'online'
console.log(Book.prototype.type)              // online

实例:

<body>
      <div id="dv"></div>
      
</body>
<script>

      var divObj = document.getElementById('dv');
      console.log(divObj);
      console.log(divObj.__proto__);       // HTMLDivElement
      console.log(divObj.__proto__.__proto__)      // HTMLElement
      console.log(divObj.__proto__.__proto__.__proto__)     // Element
      console.log(divObj.__proto__.__proto__.__proto__.__proto__)      //    Node
	  console.log(divObj.__proto__.__proto__.__proto__.__proto__.__proto__)             //   EventTarget
	  console.log(divObj.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__)     //   Object
	  console.log(divObj.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__)	       // null  
      
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值