javascript原型对象prototype
“我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。”
引用类型才具有prototype属性,包含:
var fn=new String("text");
String.prototype.value="val";
console.log(fn.value); //val
function Person(name){
this.name=name;
}
Person.prototype.getName = function() {
return this.name;
};
var p1 = new Person("Evan");
console.log(p1.name); //Evan
console.log(p1.getName()); //Evan
这个prototype属性也就相当于动态添加属性或方法
再看一个更详细的例子:
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
console.log(this.name)
};
var person1 = new Person();
var person2 = new Person();
person2.sayName(); //Nicholas
console.log(person1.sayName == person2.sayName); //true
一张图看各对象的关系:

Person里面只有一个prototype属性,指向原型对象。原型对象中constructor指向它的构造函数(它的来源),和其他原型属性方法。
Person.prototype就是原型 isPrototypeOf确定二者是否有关系,Object.getPrototypeOf获取原型值
console.log(Person.prototype); //Object {name: "Nicholas", age: 29, job: "Software Engineer"} (原型对象)
console.log(Person.prototype.isPrototypeOf(person1)) //true;
console.log(Object.getPrototypeOf(person1).name) //Nicholas;
console.log(Person.prototype.constructor == Person); //true
若将上例稍改一下,给实例化的person1添加name属性并赋值: name:me

↑
person1.name = "me"; //先在实例中找,没有再到原型中找
console.log(person1.name);//me
console.log(person1.constructor == Person);//true //用hasOwnPrototy()检测是否在实例中,为false说明属性来自原型
console.log(person1.hasOwnProperty("name")) ;//true
console.log(person2.hasOwnProperty("name")) ;//false //用一个in,检测是否有次属性,无论在实例还是原型中
console.log("name" in person1) ;//true
console.log("name" in person2) ;//true
若更改整个 Person.prototype:
Person.prototype = {xx:"xx"};
person1.xx; //undefined
var ppp=new Person();
ppp.xx; //输出:xx
只会改变后面实例的对象,之前的不会改变。之前引用的不会被垃圾清理。
person1和person2是实例化的Person,也能访问Person的原型对象,用指针[[Prototype]]来实现,我们不可操作[[Prototype]],但可以有另一个__proto__来访问。
接上例。
↑
console.log(person1.prototype);//undefined
console.log(Person.prototype);//Object {name: "Nicholas", age: 29, job: "Software Engineer"}
console.log(person1.__proto__);//Object {name: "Nicholas", age: 29, job: "Software Engineer"}
console.log(Person.__proto__);//function(){}
实例化对象调用原型对象,是__proto__指针,不是prototype属性。它本身没有原型对象,是去调用构造函数的原型对象。
当构造函数(Person)调用__proto__指针时,返回它本身。
__proto__与prototype的区别:(IE不支持__proto__)
__proto__:对象的内部原型的引用。
prototype :返回是对象的原型。
当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概 念。所以__proto__是联系各对象的桥梁。
var Person = function () { };
var p = new Person();
alert(p.__proto__ === Person.prototype); //true
这个例子很容易理解,实例p的来源就是Person的原型
看一个复杂的例子:
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary = 50000;
var Programmer = function () { };
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function () {
alert("programmer writes code");
};
Programmer.prototype.Salary = 500;
var p = new Programmer();
p.Say();
p.WriteCode();
alert(p.Salary);
我们来做这样的推导:
var p=new Programmer()可以得出p.__proto__=Programmer.prototype;
而在上面我们指定了Programmer.prototype=new Person();我们来这样拆分,var p1=new Person();Programmer.prototype=p1;那么:
p1.__proto__=Person.prototype;
Programmer.prototype.__proto__=Person.prototype;
由根据上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。
好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去p.__proto__,也就是 Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去p.__proto__.__proto__,也就是 Person.prototype中去找,于是就找到了alert(“Person say”)的方法。
(参考:http://rockyuse.iteye.com/blog/1426510)
var student = {name:'aaron'};
console.log(student.__proto__);//Object {}
JS中的所有对象都是继承自Object对象,所以这里来源是Object {}
关于继承
function Animal(){}
Animal.prototype.say=function(){return "www"};
function Person(){}
Person.prototype.say=function(){return "hello"};
Person.prototype = new Animal();
6 var p2 = new Person();
p2.say(); //www
当一个对象的prototype指向另一对象时,就实现了继承。如例子中Person继承Animal
此时,要注意,父类和子类都有自己的prototype。继承后,子类的实例对象构造函数就指向父类了。如下
↑
console.log(p2.constructor);//function Animal(){}
console.log(Object.getPrototypeOf(Person.prototype).constructor) ;//function Animal(){}
按道理这很正常,理应如此。但有时不是我们想要的结果。如上例子,虽然继承了父类,但 p2.say()我想让它输出子类的结果,那怎么弄呢
只需在继承后重写即可
function Animal(){}
Animal.prototype.say=function(){return "www"};
function Person(){}
Person.prototype.say=function(){return "hello"};
Person.prototype = new Animal();
Person.prototype.say=function(){return "i am people"} //这里重写父类函数
var p2 = new Person();
p2.say(); //i am people
引用类型的问题:
function SuperType(){this.color = ["red","blue","green"]}
function SubType(){
}
SubType.prototype=new SuperType();
var s1=new SubType();
s1.color.push("black");
console.log(s1.color);//["red", "blue", "green", "black"]
var s2=new SubType();
console.log(s2.color);//["red", "blue", "green", "black"]
s1和s2是子类的实例化,s1把继承父类的color属性进行添加,按理说只能s1自己添加。结果把子类实例化出的其他对象的属性都改了。
SubType.prototype=new SuperType();相当于:子类是父类的一个实例,子类自己拥有了color属性。但实例化子类时,s1和s2共享color属性,导致更改时一起改了。
这样肯定不合常理。更改
function SuperType(){this.color = ["red","blue","green"]}
function SubType(){
SuperType.call(this);
}
SubType.prototype=new SuperType();
var s1=new SubType();
s1.color.push("black");
console.log(ss.color); //["red", "blue", "green", "black"]
var s2=new SubType();
console.log(s2.color); //["red", "blue", "green"]
call()函数在闭包时有讲,把某个函数绑定到某个对象中。在这里,就相当于把父类函数拿过来,在自己作用域调用,借用构造函数,也相当于重写了父类。
所以每次实例化子类,都要调用子类重写的函数,进行一次分配,每个实例拥有自己的color属性。互不干扰。
或者这样继承:
function Person(){}
Person.prototype.language="chinese";
Person.prototype.eat= function () {
console.log("eating");
}
function Programmer(){}
Programmer.prototype=Object.create(Person.prototype);//js原生复制函数
Programmer.prototype.constructor=Programmer; //指回子类自己
Programmer.prototype.language="javascript";//覆盖父类
此文章是学习小结,如有不正,望指正。
javascript原型对象prototype的更多相关文章
- JavaScript 的原型对象 Prototype
在 JavaScript 中,每当定义一个对象(或函数)时候,对象中都会包含一些预定义的属性,其中一个属性就是原型对象 prototype. var myObject = function( name ...
- JavaScript的原型对象prototype、原型属性__proto__、原型链和constructor
先画上一个关系图: 1. 什么是prototype.__proto__.constructor? var arr = new Array; 1. __proto__是原型属性,对象特有的属性,是对象指 ...
- [js高手之路]使用原型对象(prototype)需要注意的地方
我们先来一个简单的构造函数+原型对象的小程序 function CreateObj( uName, uAge ) { this.userName = uName; this.userAge = uAg ...
- JavaScript -- 原型:prototype的使用
JavaScript -- 原型:prototype的使用 在 JavaScript 中,prototype 是函数的一个属性,同时也是由构造函数创建的对象的一个属性. 函数的原型为对象. 它主要在函 ...
- javaScript系列 [03]-javaScript原型对象
[03]-javaScript原型对象 引用: javaScript是一门基于原型的语言,它允许对象通过原型链引用另一个对象来构建对象中的复杂性,JavaScript使用原型链这种机制来实现动态代理. ...
- C# -- 等待异步操作执行完成的方式 C# -- 使用委托 delegate 执行异步操作 JavaScript -- 原型:prototype的使用 DBHelper类连接数据库 MVC View中获取action、controller、area名称、参数
C# -- 等待异步操作执行完成的方式 C# -- 等待异步操作执行完成的方式 1. 等待异步操作的完成,代码实现: class Program { static void Main(string[] ...
- js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器
一.前言 了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象. 注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别 ...
- 原型对象prototype和原型属性[[Prototype]]
构造器:可以被 new 运算符调用, Boolean,Number,String,Date,RegExp,Error,Function,Array,Object 都是构造器,他们有各自的实现方式. 比 ...
- 构造函数、原型对象prototype、实例、隐式原型__proto__的理解
(欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...
随机推荐
- 基音周期提取2-基于线性相关系数的Matlab实现
基音周期提取2-基于线性相关系数的Matlab实现 基音周期提取结果 图1 基音提取结果 算法说明 线性相关系数 也称"皮尔逊积矩相关系数"(Pearson product-mom ...
- linux进程间通信-共享内存
转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...
- PCB设计检查表
PCB设计检查表 一.确保PCB网表与原理图描述的网表一致 二.布局大致完成后需检查 外形尺寸 确认外形图是最新的 确认外形图已考虑了禁止布线区.传送边.挡条边.拼板等问题 确认PCB 模板是最新的 ...
- 电子数字 网易游戏在线笔试 第一题 hihocoder
题目链接 http://hihocoder.com/contest/ntest2016spring1/problem/1 这个题目有几个算法考点: (1)对于一个LED数码管(由7个发光二极管封装在一 ...
- 60行以内写mvc
标题党.几天前看到一个30行写mvc的文章,东施效颦,也动手写了个60行的,功能上略微扩充一些,记录下来,后面有时间可以继续优化. mvc其实是一个观察者模式.view来监听model,所以当mode ...
- PhoneGap(二维码扫描 )
关于 phoneGap 如何做 二维码扫描 1. 先配置好, 环境 http://coenraets.org/blog/cordova-phonegap-3-tutorial/http: ...
- c语言到汇编的学习
[内存结构] C程序通过编译-汇编-连接,最后到可执行文件.载入内存有这几个部分: text:正文段,存放的是可执行的机器码段 data:存放初始化之后的全局变量和静态变量 bbs:存放未初始化的静态 ...
- Windows的bat脚本中for循环
转载至 http://123304258.blog.163.com/blog/static/12354702012621103256608/ [删除目录下某种格式的文件 ] for /r f:\ ...
- \(\S1\) 描述性统计
在认识客观世界的过程中,统计学的思想和方法经常起着不可替代的作用.在许多工程及自然科学的专业领域中,包括可靠性分析.质量控制.生物信息.脑科学.心理分析.经济分析.金融风险管理.社会科学推断.行为科学 ...
- 【原创】还原Hyper-V 到一个新的虚拟机
Context: I need to restore VM31 backup (via 'Windows Server Backup' tool) as another new Hyper-V mac ...