prototype与_proto_

对象的 prototype 属性的方法、属性为对象所属的那一“类”所共有。对象原型链通过 proto 属性向上寻找。

proto 指定 null 之外的原始类型(Number, String, Boolean, undefined, Symbol)值是无效的。

通过构造函数或者 {} 方式创建的对象的 prototype 属性默认为 undefined

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
};

// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

如果没有明确指定,那么 proto 默认为 Object.prototype,而Object.prototype 自身也有 proto ,值为 null,是原型链的终点。

构造函数模式的继承

// a constructor function
function Foo(y) {
  // which may create objects
  // by specified pattern: they have after
  // creation own "y" property
  this.y = y;
}

// also "Foo.prototype" stores reference
// to the prototype of newly created objects,
// so we may use it to define shared/inherited
// properties or methods, so the same as in
// previous example we have:

// inherited property "x"
Foo.prototype.x = 10;

// and inherited method "calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

// now create our "b" and "c"
// objects using "pattern" Foo
var b = new Foo(20);
var c = new Foo(30);

// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

// let's show that we reference
// properties we expect

console.log(

  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true

  // also "Foo.prototype" automatically creates
  // a special property "constructor", which is a
  // reference to the constructor function itself;
  // instances "b" and "c" may found it via
  // delegation and use to check their constructor

  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo, // true

  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true

);

如果没有明确指定,通过构造函数创建的对象的 proto 属性值为构造函数的 prototype 属性。

下面的写法在javascript是很常见的,但是javascript中的new的执行过程是怎么样子的呢?看下面写法:

var Person = function(name) {
    this.name = name;
}
var p = new Person();

new操作符的操作是:

var p = {}

p.proto = Person.prototype

Person.call(p)

var p={}; 也就是说,初始化一个对象p。

p.proto = Person.prototype;

Person.call(p);也就是说构造p,也可以称之为初始化p。

var Person = function() {}
var p = new Person();
alert(p.__proto__ ==  Person.prototype)

这段代码会返回true。说明我们步骤2的正确。

那么proto是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是proto,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去proto里找这个属性,这个proto又会有自己的proto,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

按照标准,proto是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

好,概念说清了,让我们看一下下面这些代码:

var Person = function () { };
Person.prototype.Say = function () {
    alert("Person say");
}
var p = new Person();
p.Say(); 

这段代码很简单,相信每个人都这样写过,那就让我们看下为什么p可以访问Person的Say。

首先var p=new Person();可以得出p.proto=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性,于是,他就需要到他的proto中去找,也就是Person.prototype,而我们在上面定义了Person.prototype.Say=function(){}; 于是,就找到了这个方法。

好,接下来,让我们看个更复杂的。

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”)的方法。

其余的也都是同样的道理。

1.总共三类对象(蓝色大框)

2.实例对象(通过new XX() 所得到的实例),跟原型链相关的只有 proto 属性,指向其对应的原型对象 *.prototype 。

3.构造函数对象分原生和自定义两类。跟原型链相关的有 proto 属性,除此之外还有 prototype 属性。它们的 proto 属性都是指向 Function.prototype 这个原型对象的。prototype 也是指向对应的原型对象。

4.原型对象除了一样拥有 proto 外,也拥有独有的属性 constructor 。它的proto 指向的都是 Object.prototype ,除了 Object.prototype 本身,它自己是指向 null 。而 constructor 属性指向它们对应的构造函数对象。

5.原型链是基于 proto 的。实例只能通过其对应原型对象的 constructor 才能访问到对应的构造函数对象。构造函数只能通过其对应的 prototype 来访问相应的原型对象。

function People(name)
{
  this.name=name;
  //对象方法
  this.Introduce=function(){
    alert("My name is "+this.name);
  }
}
//类方法
People.Run=function(){
  alert("I can run");
}
//原型方法
People.prototype.IntroduceChinese=function(){
  alert("我的名字是"+this.name);
}

//测试

var p1=new People("Windking");
p1.Introduce();
People.Run();
p1.IntroduceChinese();
function Father(){
                this.name = "lisi";
                this.con = function(){
                    console.log("aaa")
                }

            }
            Father.prototype.use = function(){
                alert("use")
            }
var s = new Father();
            for(var i in s){
                console.log(  i  );
            }
//name,con,use

JavaScript原型的更多相关文章

  1. 浅谈系列之 javascript原型与对象

    在我学习与使用javascript三个月中,我一直对javascript的继承关系以及prototype理解不清,导致很多时候为什么这么用说不出个所以然来.截止到本周为止,通过之前的学习以及自己的再学 ...

  2. JavaScript原型OOP——你上车了吗?

    .title-bar { width: 80%; height: 35px; padding-left: 35px; color: white; line-height: 35px; font-siz ...

  3. 深入理解javascript原型和闭包 (转)

    该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...

  4. 深入理解javascript原型和闭包系列

    从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...

  5. 深入理解javascript原型和闭包(1)——一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...

  6. 深入理解javascript原型和闭包(2)——函数和对象的关系

    上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...

  7. 深入理解javascript原型和闭包(3)——prototype原型

    既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...

  8. 深入理解javascript原型和闭包(4)——隐式原型

    注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...

  9. 深入理解javascript原型和闭包(5)——instanceof

    又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...

  10. 深入理解javascript原型和闭包(6)——继承

    为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中 ...

随机推荐

  1. 萌新笔记——C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)

    萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...

  2. SqlServer SET IDENTITY_INSERT ON | OFF

    想要将值插入到自动编号(或者说是标识列,IDENTITY)中去,需要设定 SET IDENTITY_INSERT 示例: 1.首先建立一个有标识列的表: )) 2.尝试在表中做以下操作: , 'gar ...

  3. 烂泥:学习centos之快速搭建LNMP环境

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 以前在centos下安装软件都是喜欢源码安装,不过昨天因为一个事情需要一个centos 下的LNMP环境.反倒不会搞了,今天特意记录下,以备后续使用. 一 ...

  4. wamp下Apache配置vhost

    1.由于后面虚拟机中需要用到Rewrite所以先编辑Apache的conf目录下的httpd.conf文件.(我的文件位置是:D:\Program Files\wamp\bin\apache\apac ...

  5. redis 学习笔记(7)-cluster 客户端(jedis)代码示例

    上节学习了cluster的搭建及redis-cli终端下如何操作,但是更常用的场景是在程序代码里对cluster读写,这需要redis-client对cluster模式的支持,目前spring-dat ...

  6. hql中in关键字的用法

    hql: from " + FoodComment.class.getName() + " f where f.id in :groupIds" 封装的方法: publi ...

  7. CSS:position:fixed使用(转)

    position属性规定元素的定位类型,即建立元素布局所用的定位机制.任何元素都可以定位,不过绝对定位或固定定位元素会生成一个块级框,而不论该元素本身是什么类型.相对定位元素会相对于它在正常流中的默认 ...

  8. HTML隐藏的方法

    display:none; 表单 type="hidden" 宽高设为0 height:0;width:0; 祖先元素隐藏或在页面外 margin Visibility:hidde ...

  9. wpf ListBox删除

    绑定一个GUID对象 重绑定的数组中移除改对象,重新绑定.

  10. ffmpeg获取文件的总时长(mp3/mp4/flv等)

    使用ffmpeg.exe获取文件属性信息,C#中可以在进程外异步调用这个工具,如下: using (System.Diagnostics.Process pro = new System.Diagno ...