zoukankan      html  css  js  c++  java
  • 面向对象与原型2---原型

    1.

    我们创建的每个函数(或称构造函数或对象)都有一个 prototype(原型)属性,这个属性是一个对象(这个对象下有个prototype属性,而这个属性其实是另外一个对象的引用,这个属性就是一个对象),它的用途是

    包含可以由特定类型的所有实例共享的属性和方法(prototype共享放到其中的属性和方法,无论实例化多少对象,属性和方法都是共享的。这样有好处也有坏处。)。逻辑上可以这么理解:prototype 通过
    调用构造函数而创建的那个对象的原型对象。使用原型的好处可以让所有对象实例共享它所
    包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息
    添加到原型中。

    //构造函数声明对象方式

    function Box(name,age) {

    this.name = name;    //实例属性

    this.age=age;

    this.run = function(){  //实例方法

     return this.name + this.age + '运行中...';

    }

    //原型声明对象方式

    function Box(){}  //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实习方法
    Box.prototype.name = 'Lee'; //原型属性  原型里添加属性
    Box.prototype.age = 100;
    Box.prototype.run = function () {  // 原型方法  在原型里添加方法
    return this.name + this.age + '运行中...';
    };
    比较一下原型内的方法地址是否一致:
    var box1 = new Box();

    alert(box1.name);  //输出lee

    alert(box1.run());  //输出lee运行中

    var box2 = new Box();
    alert(box1.run == box2.run); //true,方法的引用地址保持一致

    以上两个例子说明:

    如果是实例方法,不同的实例化,他们的方法地址是不一样的,是唯一的

    如果是原型方法,那么他们的地址是共享的,大家都一样

    2.

    为了更进一步了解构造函数的声明方式和原型模式的声明方式,我们通过图示来了解一
    下:

    (1)构造函数方式中

    box1和box2 的实例属性实例方法在内存中是不共享的,box1的name属性和box2的name属性的地址是不同的

    (2)原型方式中

    function Box(){}  
    Box.prototype.name = 'Lee'; 
    Box.prototype.age = 100;
    Box.prototype.run = function () {  
    return this.name + this.age + '运行中...';
    };
    var box1 = new Box();//Box实例有了,但是里面为空,实际上里面有个自带的属性_proto_

    var box1 = new Box();

    alert(box1.prototype);// undefined 这个属性是一个对象,访问不到

    alert(box1._proto_);  // 输出 object 这个属性是一个指针,指向prototype原型对象,但是_proto_在ie浏览器中是不支持的

     创建的每个函数都有一个 prototype(原型)属性,但是这里访问不到,应该访问的是那个指针_proto_

    _proto_实际上就是prototy,只不过他是个指针属性,指向prototype对象

    在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__
    属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性 constructor,而constructor指向Box,
    通过这两个属性,就可以访问到原型里的属性和方法了。
    PS:IE 浏览器在脚本访问__proto__会不能识别,火狐和谷歌浏览器及其他某些浏览器
    均能识别。虽然可以输出,但无法获取内部信息。
    alert(box1.__proto__); //[object Object]

    alert(box1.constructor);  //输出 function  Box(){ } 。constructor是构造属性,可以获取构造函数本身  作用是通过被原型指针定位,然后得到构造函数本身,其实就是做一个连接的作用,就是对象实例对应原型对象的作用

    以下图是在控制台打出的:

    3.
    判断一个对象实例(对象引用)是否指向了该构造函数的原型对象,可以使用 isPrototypeOf()方法来测试。只要实例化了,他是自动指向的。
    alert(Box.prototype.isPrototypeOf(box1)); //true    只要实例化对象,即都会指向

    例如:

    var obj = new Object();

    alert(Object.prototype.isPrototypeOf(obj)); //true

    说明只要实例化了,就默认指向

    alert(Object.prototype.isPrototypeOf(box1));  //true  因为所有的实例都是Object

    alert(Box.prototype.isPrototypeOf(obj));   //false

    4.

    原型模式的执行流程:
    1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
    2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;

    function Box(){} // 构造函数函数体内什么都没有,如果有,叫做实例属性和实例方法
    Box.prototype.name = 'Lee';   //原型属性
    var box1 = new Box();

    alert(box1.name);  //输出 Lee  构造函数实例里没有,则去它的原型对象里找

    box1.name = 'jack';   //实例属性 并没有重写原型

    alert(box1.name);   //输出 jack  就近原则  先查找构造函数实例里的属性或方法,如果有,立刻返回

    var box2 = new Box();

    alert(box2.name);  //实例属性不会共享,所以box2访问不到实例属性,只能访问到原型属性

    delete box1.name;  //删除实例中的属性

    alert(box1.name);  //输出lee

    delete Box.prototype.name //删除原型中的属性

    alert(box1.name);  // undefined

    Box.prototype.name = 'kk';  //覆盖原型中的属性

    alert(box1.name);  //输出kk

    如果:

    function Box(){

    this.name = 'jack';  //实例属性

    }

    Box.prototype.name = 'Lee';   //原型属性
    var box1 = new Box();

    alert(box1.name);  //输出 jack

    5.

    如何判断属性是在构造函数的实例里,还是在原型里?可以使用 hasOwnProperty()函数
    来验证:

    //判断实例中是否存在指定属性

    alert(box.hasOwnProperty('name')); //实例里有返回 true,否则返回 false

    //判断原型中是否存在指定属性

    就近原则,box1访问Jack,而不是Lee; box2访问Lee,因为没有实例属性

    in 操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原
    型中。
    alert('name' in box); //true,存在实例中或原型中

    我们可以通过 hasOwnProperty()方法检测属性是否存在实例中,也可以通过 in 来判断
    实例或原型中是否存在属性。那么结合这两种方法,可以判断原型中是否存在属性。且只能判断原型中是否存在。

    function isProperty(object, property) { //判断原型中是否存在属性
    return !object.hasOwnProperty(property) && (property in object);  //实例中没有&&原型或实例中有=>原型中有
    }
    var box = new Box();
    alert(isProperty(box, 'name')) //true,如果原型有

  • 相关阅读:
    Sublime Text 3插件收集
    Jenkins连接git时出现“Failed to connect to repository : Command ... HEAD" returned status code 128:”的问题解决
    Jenkins错误“to depth infinity with ignoreexternals:true”问题解决
    jeesite导入数据库错误:java.sql.SQLException: Incorrect string value: 'xE4xB8xADxE5x9BxBD' for column 'name' at row 1问题解决
    Maven出现错误No plugin found for prefix 'jetty' in the current project and in the plugin groups的问题解决
    Mac下关闭Sublime Text 3的更新检查
    Ueditor 专题
    Navicat PatchNavicat
    DataSourceBuilder.create().build()
    常用的HTML富文本编译器UEditor、CKEditor、TinyMCE、HTMLArea、eWebEditor、KindEditor简介
  • 原文地址:https://www.cnblogs.com/mabelstyle/p/3719853.html
Copyright © 2011-2022 走看看