昨天看对原型概念有了一点点的兴趣,虽说了解的不是很透彻,但是还是多多少少有一点收获的,就自己的一些学习到的东西做一个小小的总结。主要是结合了课本、网上资源和一些视频来学习的。
原型涉及到了原型、原型链和构造函数。而且在每个博客的讲解中都涉及到了构造函数的内容,那就先从构造函数的概念和作用谈起。
构造函数
构造函数我们应该都很清楚了,在学习C#的时候接触过这个概念。在JS的学习中:构造函数的特点:
a:构造函数的首字母必须大写,用来区分于普通函数
b:内部使用的this对象,来指向即将要生成的实例对象
c:使用New来生成实例对象
例如:
//构造函数
function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name +"say hello");
}
}
var boy = new Person("bella",23);
boy.sayHello(); // bella say hello
构造函数的缺点:
所有的实例对象都可以继承构造器函数中的属性和方法。但是,同一个对象实例之间,无法共享属性
解决思路:
a:所有实例都会通过原型链引用到prototype
b:prototype相当于特定类型所有实例都可以访问到的一个公共容器
c:那么我们就将重复的东西放到公共容易就好了
如下显示:
function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name + "say hello");
}
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //false
原型
prototype(原型):是function对象的一个熟悉性,定义了构造函数制造出的对象的公共祖先(公共属性和方法)通过构造函数产生对象,可以继承改变原型的属性和方法。原型也是对象。
__proto__(隐士原型):每个对象的__proto__属性指向自身构造函数的prototype;
constructor(构造器):返回对创建此对象的数组函数的作用。
prototype属性的作用
js中每个数据类型都是对象,除了null 和 undefined,而每个对象都是继承自一个原型对象,只有null除外,它没有自己的原型对象,最终的Object的原型为null
function Person(name,age){
this.name = name;
this.age = age;
}
Person.propotype.sayHello = function(){
console.log(this.name + "say hello");
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //true
由上图可以看出,prototype是构造函数的属性,而consructor则是构造函数的prototype属性所指向的那个对象,也就是说constuctor是原型对象的属性。
constructor属性是定义在原型对象上面,意味着也可以被实例对象继承。
- 如果有原型,那么就一定有函数。每一个对象有一个属性叫__proto__;这个属性就是对象的原型。对象有原型,那么原型也是对象,原型也有原型。
- 所有的函数是对象,继承自Function.prototype
- Function.prototype是对象,继承自Object.prototype
- Object.prototype是对象,继承自null
- obj是对象,继承自Object.prototype
- Function是对象,继承自Function.prototype
- Function是函数,继承自Function.prototype
这就涉及到了原型链。
原型链
首先看一段代码:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
</style>
<script type="text/javascript">
var o = {}; //{ name:"我是祖宗"};
var f1 = function() {
// this.name = "我是亚当";
};
f1.prototype=o;
var foo1 = new f1();
var f2 = function() {
// this.name = "夏娃";
}
var foo2 = new f2();
foo2.__proto__ = foo1;
var f3 = function() {
// this.name = "我是人类";
};
f3.prototype = foo2;
var foo3 = new f3();
alert(foo3.name);
</script>
</head>
<body>
</body>
</html>
上面代码的运行结果:
1)当所有的this.name,都没有注释的话:运行结果----》我是人类
2)当f3的this.name 注释掉,运行结果-----》我是夏娃
3)当f2和f3中的this.name注释,运行结果是-----》我是亚当
4)当f1,f2,f3中的this.name注释,运行结果----》我是祖宗,
5)当全部被注释掉,运行结果是undefined;
js成员的访问规则
- o.方法()
- 首先在o当前这个类型中寻找该成员的定义,如果存在该成员的定义
- 那么就直接使用改成员
- 如果该成员不再当前类型中,就访问其原型(原型链中的上一级)
- 以此类推,直到null位置
上图中的原型链:
对象 | __proto__ | prototype | constructor |
foo | Foo.prototype | --- | --- |
obj | Object.prototype | --- | --- |
Foo | Function.prototype | Foo.prototype | |
Foo.prototype | Object.prototype | --- | Foo |
Function | Function.prototype | Function.prototype | |
Function.Prototype | Object.prototype | --- | Function |
obj | Object.prototype | --- | --- |
Object | Function.prototype | Object.prototype | --- |
Object.prototype | null | --- | Object |
参考链接: