引用数据类型分类
-
函数数据类型:
- 普通函数
- 内置类(如
Array
,Date
)- 自己创建的类(只要是new创建出来的都是类)
-
对象数据类型:
- 普通对象、数组、正则、Math、arguments...
- 实例(除了基本类型的字面量创建的值)
- prototype的值
- 函数
原型和原型链的定义
- 所有的
都天生自带一个属性:
prototype
(原型),这个属性的值是一个对象,浏览器会默认给它开辟一个堆内存。 - 在浏览器给
prototype
开辟的堆内存中有一个天生自带的属性constructor
,这个属性存储的值是当前函数本身,prototype
里的属性和方法对于实例是公有的方法,对于原型自己是私有方法。
3.每一个都有一个
__proto__
的属性,这个属性指向当前实例的
prototype
,(如果不能确定它是谁的实例,都是Object
的实例)
原型和原型链机制
在这里ary
既是Array
的实例,
因为它能通过_proto_
找到Array
的prototype
,同样根据原型链的查找机制,Array
的_proto_
指向了Obejct
的prototype
,所以ary
也是Obejct
的实例。也就是说,如何判断某个实例是不是属于某个类,就判断这个实例的原型链上是不是有这个类。
原型链是一种基于_proto_
向上查找的机制,当我们操作实例的某个属性或者方法的时候,首先找自己空间中私有的属性或者方法 如果找到了则结束查找,使用自己私有的即可,没找到则基于_proto_
找所属类的prototype
,如果找到就用这个公有的,如果没找到就基于原型上的_proto_
继续向上查找,一直找到Obejct
的原型为止,如果再没有,操作的原型或者方法不存在。
例如:
//34.原型链和原型链的查找机制
function Fn() {
var n = 100;
this.AA = function () {
console.log(`AA[私有]`);
};
this.BB = function () {
console.log(`BB[私有]`);
};
}
Fn.prototype.AA = function () {
console.log(`AA[公]`);
};
var f1 = new Fn;
var f2 = new Fn;
console.log(f1.n);
![](https://img.haomeiwen.com/i18392927/7450325c5ed83873.png)
原型修改
如果我们是在原型上增加或者修改属性或者方法这不会修改原型的constructor
function Fn() {
...
}
fun.prototype.a = function () {
...
}
fun.prototype.b = function () {
...
}
原型重定向
在实际项目基于面向对象开发的时候(构造原型设计模式),我们根据需要,很多时候会重定向类的原型(让类的原型指向自己开辟的堆内存)
如果自己进行原型的重定向,需要注意以下问题:
- 自己开辟的堆内存中没有
constructor
属性,导致类的原型构造函数缺失 -
当原型重定向后,如果原来的原型堆内存没有被重定向之前创建的实例所指向(重定向之前的实例指向原有原型),那么浏览器默认开辟的那个原型堆内存会被释放掉,如果之前已经存储了一些方法或者属性,这些东西都会丢失(所以:内置类的原型不允许重定向到自己开辟的堆内存,因为内置类原型上自带很多属性方法,重定向后都没了,这样是不被允许的)
内置类原型不能重定向
内置类原型不能重定向
当我们需要给类的原型批量设置属性和方法的时候,一般都是让原型重定向到自己创建的对象中。
function Fn() {
...
}
Fn.prototype = {
constructor: Fn, //如果不写这个,默认根据原型链查找会指向Object
aa: function () {
}
}
//41.课件7&练习题讲解[15]-构造函数和原型链的运行机制
1.function Fn() {
2. this.x = 100;
3. this.y = 200;
4. this.getX = function () {
5. console.log(this.x);
6. }
7.}
8.Fn.prototype.getX = function () {
9. console.log(this.x);
10.};
11.Fn.prototype.getY = function () {
12. console.log(this.y);
13.};
14.var f1 = new Fn;
15.var f2 = new Fn;
16.console.log(f1.getX === f2.getX);
17.console.log(f1.getY === f2.getY);
18.console.log(f1.__proto__.getY === Fn.prototype.getY);
19.console.log(f1.__proto__.getX === f2.getX);
20.console.log(f1.getX === Fn.prototype.getX);
21.console.log(f1.constructor);
22.console.log(Fn.prototype.__proto__.constructor);
23.f1.getX();
24.f1.__proto__.getX();
25.f2.getY();
26.Fn.prototype.getY();
![](https://img.haomeiwen.com/i18392927/1cd0474dce0b0146.png)
![](https://img.haomeiwen.com/i18392927/71567c51bfe96fa6.png)
//44.课件10&练习题讲解[18]-关于原型重定向问题.flv
function fun() {
this.a = 0;
this.b = function () {
alert(this.a);
}
}
fun.prototype = {
b: function () {
this.a = 20;
alert(this.a);
},
c: function () {
this.a = 30;
alert(this.a)
}
};
var my_fun = new fun();
my_fun.b();
my_fun.c();
![](https://img.haomeiwen.com/i18392927/ad7d14554894d0ad.png)
![](https://img.haomeiwen.com/i18392927/337f5e136d8c8816.png)
![](https://img.haomeiwen.com/i18392927/0097d5306d580717.png)
//45.课件11&练习题讲解[19]-关于原型重定向问题综合练习
function Fn() {
var n = 10;
this.m = 20;
this.aa = function () {console.log(this.m);}
}
Fn.prototype.bb = function () {console.log(this.n);};
var f1=new Fn;
Fn.prototype={
aa:function(){console.log(this.m+10);}
};
var f2=new Fn;
console.log(f1.constructor);
console.log(f2.constructor);
f1.bb();
f1.aa();
// f2.bb();
f2.aa();
f2.__proto__.aa();
答案:
console.log(f1.constructor);//Fn
console.log(f2.constructor);//Object
f1.bb();//undefined
f1.aa();//20
f2.bb();//报错:f2.bb is not a function
f2.aa();//20
f2.__proto__.aa();//NaN
![](https://img.haomeiwen.com/i18392927/51cedf24ec9608a8.png)
网友评论