设为首页 加入收藏

TOP

JavaScript原型,原型链(一)
2015-12-01 14:11:39 来源: 作者: 【 】 浏览:10
Tags:JavaScript 原型

js原型


问题:什么是js原型?


js每声明一个function,都有prototype原型,prototype原型是函数的一个默认属性,在函数的创建过程中由js编译器自动添加。


也就是说:当生产一个function对象的时候,就有一个原型prototype。


举个例子:



是不是还看到了一个_proto_的属性?!骚年,你的眼睛不错~待会在解释prototype和_proto_的基友关系!


prototype的属性值是一个对象,是属性的集合,是属性的集合,是属性的集合,重要事情说三遍!


为什么要说他的属性的集合呢?我再来举个例子~:


function Person(name,age){
? ? this.name=name;
? ? this.age=age;
}
? ? Person.prototype.sayHello=function(){
? ? alert("使用原型得到Name:"+this.name);
}
var per=new Person("alin",21);
per.sayHello(); //输出:使用原型得到Name:alin


在函数Person里面自定义了属性name和age,而prototype是我们的属性集合,也就是说,我要添加sayHello这个属性到Person,则要这样写:Person.prototype.sayHello,就能添加Person的属性。


(我们可以简单的把prototype看做是一个模板,新创建的自定义对象都是这个模板prototype的一个拷贝,其实准确来说,不应该说是一个拷贝,而是一个连接,只不过这种链接是不可见,新实例化的对象内部有一个看不见的_Proto_指针,指向原型对象)。


使用原型来优化代码:


普通code:


function add(x,y){
? return x+y;
}
function subtract(x,y){
? return x-y;
}
console.log(add(1,3));


第一种方式用原型优化后:


var Calculator = function(){
?
};
Calculator.prototype = {
? ? add:function(x,y){
? ? return x+y;
},
subtract:function(x,y){
? ? return x-y;
}
};
console.log((new Calculator()).add(1,3));


第二种方式用原型优化后:


?var Calculator = function () {};
Calculator.prototype = function(){
? add = function(x,y){
? return x+y;
},
subtract = function(x,y){
? ? return x-y;
}
return{
? ? add:add,
? ? subtract:subtract
}
}();
?
console.log((new Calculator()).add(1,3));   


它目的:封装私有的function,通过return的形式暴露出简单的使用名称,以达到public/private的效果。
?
------------------------------------华丽的分割线------------------------------------


js原型链
问题:什么是原型链?
根据《java script高级程序设计》P162页可以作出回答:原型链是实现继承的主要方法。其基本思想是:利用原型让一个引用类型继承另一个应用类型的属性和方法。
简单回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。


首先,我觉得有必要先解释一下prototype 和_proto_之间的关系。
每一个基本对象都有自己的_proto_属性,而每一个函数对象都有自己的prototype原型(函数对象也属于基本对象,所以也有_proto_),每当去定义一个prototype的时候,就相当于把该实例的__proto__指向一个结构体,那么这个被指向结构体就称为该实例的原型。 我们还是来看图吧~比较清晰:


var foo = {
? ? ? x: 10,
? ? ? y: 20
};?



解析:当你定义一个函数对象的时候,其内部就有这样一个链表关系。声明foo对象,自带了_proto_的属性,而这个属性指向了prototype,从而实现对象的扩展(例如继承等操作)。


再看一个例子:


var a = {
? ? ? x: 10,
? ? ? calculate: function (z) {
? ? ? ? ? ? ? return this.x + this.y + z
? ? ? }
};
var b = {
? ? ? ? y: 20,
? ? ? ? __proto__: a
};
?
var c = {
? ? ? ? y: 30,
? ? ? ? __proto__: a
};
?
?
b.calculate(30); // 60?



附上另外说明:


1、一个没有继承操作的函数的_proto_都会指向Object.prototype,而Object.prototype都会指向null。


2、所以,也可以很明显知道,为何null是原型链的终端。


理解了__proto__这个属性链接指针的本质。。再来理解constructor。


prototype默认的有一个叫做constructor的属性,指向这个函数本身。
一般construtor就是我们平时对函数设置的实例化对象


如上图:SuperType是一个函数,下面包括他的原型对象prototype,原型对象指向了构造函数的指针,而构造函数指回像了原型对象的内部指针,这样就形成了链式关系了。
就是说,当一个函数对象被创建时候,Function构造器产生的函数对象会运行类似这样的一行代码:
this.prototype = {constructor:this};
这个prototype对象是存放继承特征的地方。因为js没有提供一个方法去确定哪个函数是打算用来做构造器,所以每个函数都会得到一个prototype对象。constructor属性没有什么用,重要的是prototype对象。


实现原型链有一种基本模式,其代码大致如下:


function A(){
this.Aproperty = "111";
}
?
A.prototype.getA = function(){
return this.Aproperty;
};
?
function B(){
this.Bproperty = "222";
}
?
B.prototype = new A();//B继承A
B.prototype.getB = function(){
return this.Bproperty;
};
?
var C = new B();
console.log(C.getA());//111


以上定义了两个类型A和B。每个类型分别有一个属性和一个方法。它们的主要区别是B继承了A,而继承是通过创建A的实例,并将实例赋给B.prototype实现的。实现的本质是重写原型的对象,代之以一个新的类型的实例。换句话说,原来存在于A的实例中的所有属性和方法,现在也存在于B.prototype中了。在确立了继承关系之后,我们给B.prototype添加了一个方法,这样就继承A的属性和方法的基础上又添加了一个新方法。
如图:


另外一个很重要的链式继承模式:


?function A(x){
  this.x = x;
}
A.prototype.a = "a

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇二次指数平滑预测法 Python实现 下一篇读GNU官方的Make manual 之一(ch..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: