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. 建议将构造函数中的方法都定义到构造函数的原 ...
随机推荐
- 阿里云安装JDK1.7
本人阿里云选择的是CentOS 7.0系统,本系列文件将全部基于此环境. 1.下载JDK,版本为jdk-7u79-linux-x64.tar.gz 2.使用FileZilla上传至/softwar ...
- template学习一函数模板
要点: 1.模板参数在实体化的时候不能自动类型转换,只有非模板函数才可以 例如: int max(int,int); template <class T> T max(T,T); 在调用的 ...
- pundit
gem "pundit" Include Pundit in your application controller: class ApplicationController &l ...
- 解决hadoop启动后datanode无法启动问题
hadoop部署完成后datanode无法启动问题解决 1.检查是否有遗留的hadoop进程还在运行,如果有的话,先stop-all.sh或kill杀掉: 2.在master节点上,删除/tmp/ha ...
- <<数字是世界的>>读后感
我对这本书的第一印象就是很多书评中提到的,这是一本无论是否有学习过计算机专业知识的人都可以读的书.我一开始不是很能理解这些评价,我是抱着对这个问题的疑惑进行通读的,以后我发现了,它全书中都很少出现计算 ...
- 无法导入以下密钥文件: xxxx.pfx,该密钥文件可能受密码保护 的解决方案
无法导入以下密钥文件: xxxx.pfx,该密钥文件可能受密码保护.若要更正此问题,请尝试再次导入证书,或手动将证书安装到具有以下密钥容器名称的强名称 CSP: VS_KEY_A5A29909FF6D ...
- 从csdn博客搬家过来,请多关照!
之前一直在csdn博客,也写了不少关于java的文章,主要是学习java上的一些问题.想通过这种方式来加深对问题的认知,同时也可以帮助到志同道合的人,一起在编程的道路上共进,共勉.
- JavaScript 基础第七天(DOM的开始)
一.引言 JavaScript的内容分为三个部分,这三个部分分别是ECMAScript.DOM.BOM三个部分组成.所谓ECMAScript就是JavaScript和核心基础语法,DOM是文档对象模型 ...
- 开启个人blog~
希望自己能坚持写blog,不断的总结,不断的沉淀.
- unity渲染层级关系小结(转存)
最近连续遇到了几个绘制图像之间相互遮挡关系不正确的问题,网上查找的信息比较凌乱,所以这里就把自己解决问题中总结的经验记录下来. Unity中的渲染顺序自上而下大致分为三层. 最高层为Camera层,可 ...