JavaScript中的原型和原型链

  /*
    1.javascript中 万物皆对象
    2.但是对象是有区别的, 分为普通对象(object)和函数对象(function)
    3.规则一: 凡是通过new Function()创建的对象都是函数对象, 其他的都是普通对象
    4.Object和Function 都是通过new Function()创造的!
     */
    function fn1(){}
    var fn2 = function () {}
    var fn3 = new Function();
    console.log(typeof fn1);  // function
    console.log(typeof fn2);  // function
    console.log(typeof fn3);  // function


    var obj1 = {};
    var obj2 = new Object();
    var obj3 = new fn1();
    var obj4 = new fn3();

    console.log(typeof obj1);  // object
    console.log(typeof obj2);  // object
    console.log(typeof obj3);  // object
    console.log(typeof obj4);  // object

    console.log(typeof Function);  // function
    console.log(typeof Object);  // function

    console.log("************************************************")

    // 5.在js中, 每当定义一个对象的时候, 对象中都会包含一些预定的属性, 其中函数对象就有一个属性叫prototype
    // 6.普通对象没有prototype, 但是有__proto__
    // 7.原型对象就是普通对象, 除了Function.prototype

    /*
    var temp1 = new fn1();
    fn1.prototype.name = "张三"  temp1.name === "张三"
    typeof temp1 ===object  ====> fn1.prototype 是 普通对象

    var temp2 = new Function();
    Function.prototype.name = "小黑"  temp2.name === "小黑"
    typeof temp2 === function   ====>  Function.prototype 是 函数对象!
     */

    var temp1 = new fn1();
    fn1.prototype.name = "张三";  
    console.log(temp1.name === "张三"); // true
    Array.prototype.sayhello= function () {
        console.log("张三你好");
    }
    var arr = new Array();
    arr.sayhello();   // 张三你好


    console.log(obj1);
    console.log(fn1.prototype);
    console.log(typeof fn1.prototype);
    console.log(typeof Function.prototype);


    //8.原型对象的作用: 主要用来做继承
    // 问题: 如果构造函数和构造函数的原型对象, 都有同一个方法, 那么会优先继承构造函数的
    // 在js底层, 一般都是给父构造函数的原型对象添加方法

    var Student = function () {
        this.name = "李四";
    }

    Student.prototype.name = "张三"

    var zhangsan = new Student();
    console.log(zhangsan.name);

    //9.问题: 到底是怎样实现的继承!
    // 答案: 靠的是原型链!!!(什么是原型链, 我们等下再讲)
    console.log("***************************************");

    //10. js在创造对象的时候, 不管是普通对象还是函数对象, 都有__proto__的属性
    //11. 规则二: __proto__ 指向创建它的构造函数的原型对象
    console.log(zhangsan.__proto__);
    console.log(Student.prototype);
    console.log(zhangsan.__proto__ === Student.prototype);


    //12.构造函数Student.prototype 是谁创造的 Student.prototype是Object创造的
    //页就是说, Student.prototype.__proto__ 指向Object.prototype
    //我们心里先保留疑问, Student是谁创造 ????
    console.log(Student.prototype.__proto__ === Object.prototype);
    Object.prototype.age = "18";
    console.log(zhangsan.age);
    //13.Object.prototype.__proto__ 是 null
    console.log(Object.prototype.__proto__ === null);// true

    //13.一切归一 大家都是null创造的
    console.log(Student.__proto__ === Function.prototype);
    console.log(Object.__proto__ === Function.prototype);
    console.log(Function.__proto__ === Function.prototype);
    console.log(Function.prototype.__proto__ === Object.prototype);
    console.log(Object.prototype.__proto__ === null);// true

    //14.道德经曰: 无, 名天地之始, 所以null创造了一切!

    console.log("***************************************")
    var Animal = function () {

    }
    var Cat = function () {

    }
    Animal.jiao = function () {
        console.log("喵喵");
    }
//    Cat.prototype = Animal;
    Cat.__proto__ = Animal;
    Cat.jiao();

    // 15. 规则三: 继承的实现, 其实并不是靠prototype, 而是靠__proto__
    // 16.规则四: 原型链的作用, 在于读取对象的某个属性时, js引擎会优先查找对象本身的属性,
    // 如果没有, 会去改对象的构造函数的原型对象(prototype)上面找, 如果还是没有,
    // 就会去构造函数的原型对象的构造函数的原型对象上寻找, 如果还是找不到, 一直找下去,
    // 直到最顶层的原型对象, Object.prototype, 如果还是没有, 则返回undefined!
    // 17. 这个过程中, 维持上下层关系的靠的是__proto__

    // 题目一:
    var HrhArray = function () {

    };
    var hrhArr = new HrhArray();
    hrhArr.__proto__ = new Array();
    hrhArr.push(1);
    console.log(hrhArr);// [1]

    // 题目二:
    var obj = {};
    var Gouzao = function () {
        this.say = function () {
            console.log("哈哈");
        }
    }

    obj.__proto__ = new Gouzao();
    obj.say();
    console.log("******************************************");

    //18. 规则五: prototype(原型对象) 有一个属性  叫  constructor
    //   constructor默认指向prototype(原型对象) 所在的构造函数
    function fn5(){

    }
    console.log(fn5.prototype.constructor === fn5);
    //由于constructor属性是定义在prototype上的, 那么就意味着可以被实例对象所继承
    var obj5 = new fn5();
    console.log(obj5.constructor === fn5);

    //可以使用hasOwnProperty 方法来验证一个属性是自己的还是继承过来的
    console.log(obj5.hasOwnProperty("constructor"));


    //constructor的作用:
    //作用一: 分辨原型对象到底属于哪个构造函数
    function isInstance(Func, obj){
        return obj.constructor === Func;
    }
    console.log(isInstance(fn5, obj5));
    //作用二:可以从一个实例对象新建另一个实例对象
    function fn6() {

    }
    var x = new fn6();
    var y = new x.constructor();

    // 系统提供一个方法来判断实例对象是否为该构造函数构造----instanceof
    console.log(y instanceof fn6);
    console.log(isInstance(fn6, y));

    //作用三: 在实例方法中, 可以通过constructor调用自身的构造函数
    fn6.prototype.createCopy = function () {
        return new this.constructor();
    };
//    this.constructor 指向fn6
    var obj6 = new fn6();
    console.log(obj6.constructor === fn6)
    console.log(obj6.createCopy().__proto__ === fn6.prototype);

    //作用四: 继承!!! 非常重要!!!
    function Father(){
        this.sex = "雄性";
    }
    function Son(){
        this.age = "1";
        Son.superclass.constructor.call(this);// 相当于Father.call(this);
    }

    Son.superclass = new Father();
    var chb = new Son();

    console.log(chb.age);
    console.log(chb.sex);

    //由于constructor属性是一种原型对象与构造函数的关联关系
    //所以我们在修改原型对象的时候, 务必要小心!

    function A(){

    }

    var a = new A();
    console.log(a instanceof A);//true

    function B(){

    }
    A.prototype = B.prototype;
    console.log(a.constructor === B)//false
    console.log(a.constructor === A)//true

    console.log(a instanceof A);//false 结果失真
    console.log(a instanceof B);//false 结果失真!

    // 谨记 不要直接修改原型对象!
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页