zoukankan      html  css  js  c++  java
  • 关于JS call apply 对象、对象实例、prototype、Constructor、__proto__

    关于call与apply的理解容易让人凌乱,这里有个方法可供参考

    tiger.call(fox,arg1,arg2...)

    tiger.apply(fox,[arg1,arg2...])

    理解为

    fox入侵者,是狡猾、邪恶的入侵者,乘tiger为难之际(召唤callapply),成功欺骗tiger可怜的守卫(入口参数),入侵了tiger,

    拥有了tiger的一切:财富、老婆、孩子... 可恨、可叹tiger英雄一世,如此落入宵小之手

    关于函数对象、对象实例、prototype、Constructor、__proto__之间的关系如下图所示:

    js完全可以面向对象开发,于是对象、对象继承、实例之间如何建立彼此的关系是javascript

    语言必须要解决的问题,通过下面这张图,对象A、对象实例A1和A2,以及prototype、

    constructor(构造函数)、__proto__之前是多么巧妙地结合起来组成一张关系网;

    所以为了组成这个关系网,必须设立以下规则:

    1.任何对象都有一个属性:prototype,这个属性的类型是对象

    2. 任何对象实例都拥有constructor方法和__proto__属性

    于是对象属性prototype用于关联Prototype(虚拟),对象实例化A1A2...后,每个实例,包括Prototype

    的constructor用于关联对象,同时为了能够动态共享prototype,每个实力的__proto__属性用于关联prototype

    如此,这张关系网形成了;这实际是完美的抽象了客观世界:具备什么特质、能干什么、与其他个体是什么关系

    引用一网友的实例、辅助理解

    function base () {
    this.arr = [];
    }
    function sub (){

    }
    sub.prototype= new base();
    var a = new sub();
    var b = new sub();
    console.log(b.arr.length); //0
    a.arr[0]='moersing';
    console.log(b.arr.length); //1

    可以看出,arr是一个共享的,如果说不适用this.arr而用 var arr = [] 的话,sub访问不到,只能通过父类的闭包来访问,但是问题还是存在的。如果想继承一个完全独立的引用类型:
    第一 :
    function base () {
    this.arr = [];
    }
    function sub (){
    base.call(this);// 先加上一个实例属性
    }
    sub.prototype= new base();
    var a = new sub();
    var b = new sub();
    console.log(b.arr.length); //0
    a.arr[0]='moersing';
    console.log(b.arr.length); //0
    console.log(a.arr.length); //修改了a,b不受影响
    这个问题可以解决,但是不完美,可以看出, a和b有一个实例属性arr和一个prototype的arr,也就是说。
    a.arr[0] = 'moersing' ;
    console.log(a.arr.length); //1
    delete a.arr; //把属性实例干掉
    console.log(a.arr.length);// 这个时候访问的是 prototype的。
    所以,理论上来讲,这并不能算是完美的,变量也是需要内存的不是吗?好OK,那么,接下来,使用另一种,上面那个叫 借用继承。
    接下来这种方式比较完美,但是也不是那么复杂,主要是使用借用继承的思想罢了,也就是说,借用实例和借用原型分开。
    function base() {
    this.arr = [];
    }
    base.Constructor = function () { //添加一个原型构造函数
    //这里判断一下,如果是一个函数,并且不是一个正则表达式对象,IE7会把正则反映成一个function而不是一个object
    if (typeof this === 'function' && typeof this.prototype.source === 'undefined') {
    var fn = this.prototype;
    fn.name = 'moersing';
    fn.age = '18';
    fn.getFull = function () {
    console.log(this.name + '|' + this.age);
    };
    }
    else {
    throw new TypeError('this is not a function');
    }
    };
    function sub() {
    base.call(this); //借用构造函数,实例化一个实例属性
    }
    base.Constructor.call(sub); //再调用父类的方法,构造出一个prototype的。
    var a = new sub();
    var b = new sub();
    a.arr[0] = 'moersing'; //给a实例的引用类型添加一个元素
    console.log(a.arr.length); //结果是1
    console.log(b.arr.length); //结果是0,也就是没有收到影响
    console.log(a.name); //打印a.prototype的属性
    console.log(b.name); //打印b.prototype的属性
    b.name = 'linfo'; //修改b的。
    console.log(b.name); //linfo
    console.log(a.name); //a没有影响,还是moersing
    a.getFull(); //moerisng|18
    b.getFull(); //linfo |18

  • 相关阅读:
    如何在Oracle官网下载java的JDK最新版本和历史版本
    屏幕录制专家【Bandicam】
    Bandicam下载 + 破解
    华为荣耀7i手动更改DNS,提高网页加载速度
    SQL中使用GROUP BY注意事项
    JavaScript数据类型判断
    React.lazy和Suspense组合实现组件懒加载
    使用React+TypeScript构建自己的组件库
    leetcode-0101 对称二叉树
    leetcode-0543 二叉树的直径
  • 原文地址:https://www.cnblogs.com/jeffry/p/5344096.html
Copyright © 2011-2022 走看看