JavaScript - 面向对象编程二


上次说到了构造函数的注意事项 ! 接下来是构造函数的原型对象

构造函数的原型对象

原型对象是什么?

  • 在构造函数创建出来的时候,系统会默认帮构造函数创建并关联的一个新对象
  • 自定义构造函数的原型对象默认是一个空对象。

原型对象的作用是什么?

  • 构造函数中的原型对象中的属性和方法可以被使用该构造函数创建出来的对象使用。
  • 即以自定义构造函数方式创建出来的所有对象,自动拥有和共享该构造函数的原型对象中的所有属性和方法。

如何访问构造函数的原型对象

构造函数.protoType

如何为构造函数的原型对象添加属性和方法

  • 利用对象的动态特性来为构造函数的原型对象添加属性和方法
  • 通过我们把"构造函数的原型对象"简化为"构造函数的原型"。
  • **示例代码 : **
    //1. 提供构造函数
    function Student(number,name,age) {

        //1.1 设置对象的属性
        this.number = number;
        this.name = name;
        this.age = age;

        //1.2 设置对象的方法
        this.read = function () {
            console.log("阅读");
        }
    }

    //2. 使用构造函数来创建对象
    var stu1 = new Student("20160201","严雯",18);
    var stu2 = new Student("20160202","严二雯",16);

    //3. 设置构造函数的原型
    //3.1 为构造函数的原型对象添加属性
    Student.prototype.className = "神仙特技1班";

    //3.2 为构造函数的原型对象添加方法
    Student.prototype.description = function () {
        console.log("我的名字是" + this.name + "学号是" + this.number + "班级是" + this.className);
    };

    //4. 尝试访问
    console.log(stu1.className);
    console.log(stu2.className);
    stu1.description();
    stu2.description();
    /*
    原型属性和原型方法|实例属性和实例方法
    在构造函数内部设置的属性 => 实例属性
    在构造函数内部设置的方法 => 实例方法
    在构造函数的原型对象上设置的属性 => 原型属性
    在构造函数的原型对象上设置的方法 => 原型方法
    
    如果实例属性(方法)和原型属性(方法)存在同名,那么对象在使用属性(方法)的时候,访问的是
    实例属性(方法)还是原型属性(方法)?
    说明:使用构造函数创建的对象在访问属性或调用方法的时候:
    首先在内部查找有没有对应的实例属性(方法)
    如果有,那么就直接使用,如果没有找到,那么就继续去构造函数的原型中查找
    原型对象中如果存在该属性或方法,那么就直接使用,如果不存在指定的属性则返回undefined,如果不存在指定的方法则报错
    
    注意点
    通常在创建对象之前设置构造函数的原型对象(提供共享的属性|方法)
    访问原型对象的正确方法是 构造函数.protoType 而不是 对象.protoType
    */

使用原型解决构造函数创建对象的问题

  • 示例代码 :
//1. 提供构造函数
    function Student(number,name,age) {
        this.number = number;
        this.name = name;
        this.age = age;
    }

    //2. 设置构造函数的原型方法
    Student.prototype.description = function () {
        console.log("我的名字是" + this.name + "学号是" + this.number + "年龄是" + this.age);
    };

    //3. 使用构造函数来创建对象
    var stu1 = new Student("20170201","严雯",18);
    var stu2 = new Student("20170202","严二雯",16);

    //4. 调用创建该对象的构造函数的原型对象中的方法(检查原型方法)
    stu1.description();
    stu2.description();

    //5. 验证构造函数创建出来的多个对象共享原型对象的属性和方法
    console.log(stu1.description == stu2.description);

实例化对象和实例

  • 实例化
    通过构造函数创建具体对象的过程

  • 实例
    通过构造函数实例化出来的对象,我们称之为该构造函数的一个实例

  • **注意点 : **
    在说实例的时候,一定要指定是某个具体构造函数的实例
    示例代码 :

    //1. 提供一个构造函数
    function Person() {

    }

    //2. 根据该构造函数创建对象 == 使用Person构造函数实例化对象
    var p1 = new Person();

    //p1 是构造函数Person的一个实例

原型的使用方法

  • 利用对象的动态特性来设置原型对象
function Person(){
        this.name = "默认的名称";
    }

    //设置原型对象
    //成员= 属性|方法
    //1. 增加成员
    Person.prototype.des = "我是直立行走的人";
    Person.prototype.logName = function(){
        console.log(this.name);
    }

    //2. 修改成员
    Person.prototype.des = "我是直立行走的人++++";
    //console.log(Person.prototype);

    var p1 = new Person();
    console.log(p1.des);
    p1.logName();

    //3. 删除成员
    //delete关键字
    //语法  delete 对象.属性
    //不能用这种方式删除原型对象上面的属性(删除的是自己的属性)
    //console.log(delete p1.des);  
    // 只能通过这种方式删除
    delete Person.prototype.des ;
    console.log(p1.des);
  • 实例成员

1.实例属性
2.实例方法

  • 原型成员

1.原型属性
2.原型方法

  • 替换原型对象(字面量)
    注意点:

1.如果是替换了原型对象,那么在替换之前创建的对象和替换之后创建的对象她们指向的原型对象并不是同一个
2.构造器属性
在替换之后创建的对象中,它的构造器属性指向的不是Person构造函数,而是Object的原型对象的构造器属性

  • 建议:
    在设置完原型对象之后再统一的创建对象。
function Person(){
        this.age = 40;
    }
    var p1 = new Person();

    //var obj = new Object();
    Person.prototype = {
        // 注意:如果替换了原型对象,那么需要在原型对象中修正构造器属性
        constructor:Person,
        sayHi:function (){
            console.log("hi");
        }
    };
    var p2 = new Person();
    //p2.constructor = Person;   //在p2对象上添加了一个属性(constructor)

    //var p3 = new Person();


    //构造器属性
    console.log(p1.constructor == p2.constructor);  //false
//    console.log(p1.constructor);    //Person
//    console.log(p2.constructor);    //Object
//    console.log(p2.constructor == p2.__proto__.constructor);
//    console.log(p2.constructor == Object.prototype.constructor);

    console.log(p2);

构造器

  • 属性:constructor
  • 值:与之关联的构造函数
  • 注意点:
    constructor是在原型对象身上的,我们通过对象.constructor访问得到的值其实就是原型对象中对应的值

使用原型对象的注意事项

  • 如何访问原型对象上面的属性

1.对象.属性
2.构造函数.prototype.属性

  • 属性的访问(读取)原则

1.就近原则,在访问属性的时候,先在对象自身查找(实例属性|方法),如果找到那么就直接使用
2.如果没有找到,那么就去它的原型对象身上查找,如果找到那么就使用,找不到则undefined或者是报错

  • 设置原型属性

1.如果是左值,那么在设置对象的属性的时候,不会去原型对象上面去找(查找自己是否有,如果有就是修改,没有就是添加)
2.如果是右值,那么在读取值的时候,先查找自己,如果找不到,再去原型身上找

  • 设置原型属性的方法:

1.只能通过构造函数.prototype.属性或者是直接替换原型对象的方式来设置
2.如果原型对象的属性是引用类型的,那么可以通过对象的方式来进行设置

  • 示例代码1
function Person(){
        this.des = "默认的描述信息"
    }
    Person.prototype = {
        constructor:Person,
        des :"描述信息",
        logDes:function (){
            console.log("嘲笑我吧");
        }
    }
    //01 对象.属性
    var p1 = new Person();
    console.log(p1.des);
    //console.log(Person.prototype.des);
    p1.logDes();
    console.log(p1.age);
  • 示例代码2
function Person(){
    }
    Person.prototype = {
        constructor:Person,
        des :"描述信息",
    }
    var p1 = new Person();
    var p2 = new Person();
    //设置
    //左值 --- 右值
    //如果是左值,那么在设置对象的属性的时候,不会去原型对象上面去找(查找自己是否有,如果有就是修改,没有就是添加)
    //如果是右值,那么在读取值得时候,先查找自己,如果找不到,再去原型身上找

    //  p1.hello(左值) = "hi"(右值);
    Person.prototype.hello = "hello";
    p1.hello = "hi";

    console.log(p1.hello);  //hi
    console.log(p2.hello);  //hello
  • 示例代码3
function Person(){};
    Person.prototype.className = "逍遥派修仙技能班01";
    Person.prototype.showClassName = function(){console.log(this.className)};
    Person.prototype.car = {type:"火车",price:"$ 44444.44"};

    var p1 = new Person();
    var p2 = new Person();
    p1.showClassName();

    p1.className = "洗衣服小白";
    console.log(p1);
    console.log(p2);

    //如果原型对象的属性是引用类型的
    p1.car.type = "飞船";

    console.log(p1.car.type);   //飞船
    console.log(p2.car.type);   //飞船

    //补充
    p1.car = {type:"火箭"};
    console.log(p1.car.type);   //火箭
    console.log(p2.car.type);   //飞船

    p1.car = {};
    console.log(p1.car.type);   //undefined
    console.log(p2.car.type);   //飞船

指针

  • 如果是使用构造函数创建对象,那么在创建的对象中,有一个<proto>指针指向其构造函数对应的原型对象

  • 访问原型对象的方法

1.构造函数.prototype
2.对象.<proto>

  • 注意点:
    这个属性不是ECMA标准里的,它是部分浏览器厂商为了方便程序员开发和调试而提供的一个属性,是非标准的。
  • **示例代码 : **
    function Person(){}
    Person.prototype.des = "des";
    var p1 = new Person();

    console.log(Person.prototype == p1.__proto__);  //true

hasOwnProperty

  • in 关键字

1.检查对象中是否有指定的属性(实例属性 + 原型属性)
2.遍历对象
3.语法:“属性” in 对象

  • hasOwnProperty
    作用:检查对象中是否存在指定的属性(实例属性)
    语法:对象.hasOwnProperty("属性")

  • 需求:

1.要求判断某个属性是否是原型属性,而且仅仅只是原型属性
2.该属性存在
3.该属性不是实例属性

  • **示例代码 : **
Object.prototype.des = "des";
    Object.prototype.age = "des";
    var obj = {name:"zs",age:20};


    console.log("name" in obj);

    console.log(obj.hasOwnProperty("name"));

    console.log(obj.des);


    //in 和hasOwnProperty
    
    console.log("des" in obj);              //true
    console.log(obj.hasOwnProperty("des")); //false

    function isOnlyPrototypeProperty(propertyName,obj)
    {
        return (propertyName in obj) && !obj.hasOwnProperty(propertyName);
    }

    //验证
    console.log(isOnlyPrototypeProperty("name", obj));
    console.log(isOnlyPrototypeProperty("des", obj));
    console.log(isOnlyPrototypeProperty("age", obj));  //false

isPrototype

  • isPrototype判断是否是原型对象的
  • instanceof 判断某个对象是否是指定构造函数的实例对象
  • ** 示例代码 : **
function Person(){};
    var demo = {};
    var demo1 = {};
    Person.prototype = demo;
    Person.prototype.constructor = Person;

    var p1 = new Person();

    //判断某个对象是否是指定对象的原型对象
    console.log(demo1.isPrototypeOf(p1));

思维导图 --> 如果图片不是很清晰的话 就下载下来保存到本地查看

**Js - 面向对象编程二**
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容