• 原型和原型链


    题目:

      1.如何正确判断一个变量是数组

      2. 写一个原型链继承的例子

      3.描述 new 一个对象的过程

    知识点:

      构造函数

      构造函数-扩展

      原型规则

      原型链

      instanceof

    创建对象的几种方法:

      1. 字面量方法

        var o1 = {name:'o1'};

      2. new Object():

        var o2 = new Object({name:'o2'})

      3. 构造函数:

        var M = function(name){this.name = name};

        var o3 = new M('o3');

      4. Object.create():

        var f = {name: 'o4'};

        var o4 = Object.create(f);

    构造函数

    function Foo(name,age){
      this.name = name;
      this.age = age;
      this.class = 'class-1';
    }
    

    构造函数的扩展

      var a = {};其实就是 var a = new Object()的语法糖

      var a = []; 其实就是var a = new Array()语法糖

      function Foo(){...};其实就是 var Foo = new Function(){...}

    原型规则

       1. 所有的引用类型(数组、对象、函数),都具有对象特性,可以自由扩展属性

    var obj = {};obj.a = 100;
    var arr =[];arr.a = 100;
    function fn(){}; fn.a = 100;

       2. 所有的引用类型(数组、对象、函数),都有一个__proto__隐式原型属性

    var obj = {};obj.a = 100;
    var arr =[];arr.a = 100;
    function fn(){}; fn.a = 100;
    		
    console.log(obj.__proto__);
    console.log(arr.__proto__);
    console.log(fn.__proto__);

       3. 所有函数,都具有一个prototype显示原型属性

    function fn(){}; fn.a = 100;
    console.log(fn.prototype);

       4. 所有引用类型(数组、对象、函数)的__proto__属性值 指向它的构造函数的 prototype属性值

    var obj = {};
    var arr =[];
    function fn(){};
    
    console.log(obj.__proto__ === Object.prototype)//true
    console.log(arr.__proto__ === Array.prototype)//true
    console.log(fn.__proto__ === Function.prototype) //true

       5. 当获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即构造函数的prototype)中寻找

    function Foo(name){
      this.name = name ;      
    }
    Foo.prototype.alerName = function(){
      alert(this.name);  
    }
    
    var f = new Foo('zhangsan');
    f.printName = function(){
      console.log(this.name);  
    }
    
    f.printName();
    f.alertName();//f本身没有alertName,但Foo.prototype存在。所以可以找到并执行
    

    原型链

      简单理解就是:原型对象组成的链,一直通过__proto__属性向上找,直到找到Object的原型时结束:

    function Foo(name,age){
        this.name = name;
    }
    Foo.prototype.alertName = function(){
        alert(this.name);
    }
    var f = new Foo('zhangsan');
    f.printName = function(){
        console.log(this.name);
    }
    f.printName();
    f.alertName();
    f.toString();//要去f.__proto__.__proto__中查找
    

     以上面代码为例

     1. f没有alertName方法,所以会去f.__proto__上去查找,因为f.__proto__ === Foo.prototype ,而Foo.prototype上有该方法。所以f.alertName()可以找到并被执行

     2. f没有toString方法,所以会先去f.__proto__上去查找,Foo.prototype上也没有改方法;所以会继续去f.__proto__.__proto__上去查找(f.__proto__.__proto__ === Foo.prototype.__proto__ === Object.prototype),即Object.prototype上查找,所以f.toString()可以找到并执行

      3.Object.prototype也同样有__proto__属性,只不过有点特殊,为null

      我们把__proto__串联起来,直到Object.prototype.__proto__为止的链叫做原型链

     下面用一张图来表示:

      

    原型、实例、构造函数的关系?

      通过代码来解释

    var M = function (name) { this.name = name; };
    var o1 = new M('test');
    console.log(M.prototype === o1.__proto__);//true
    console.log(M.prototype.constructor === M);//true

      1.实例是通过new 一个构造函数生成的,即代码中 o1就是实例,M就是构造函数。

      2.构造函数的prototype属性指向的是原型(或者说原型对象)。即代码中 M.prototype === o1.__proto__

      3. 实例的__proto__属性指向的也是原型(或者说原型对象)。即 代码中 M.prototype === o1.__proto__

      4. 原型(或者说原型对象)对象的constructor指向的是构造函数。即代码中 M.prototype.constructor === M

    原型链继承的例子

      题目二解答:写一个原型链继承的例子?

    //封装DOM查询 类似jquery用法
    function Elem(id){
    	this.elem = document.getElementById(id);
    }
    //jquery中 html 方法
    Elem.prototype.html = function(val){
    	var elem = this.elem;
    	if (val){ //设置html结构
    		elem.innerHTML = val;
    		return this; //链式操作
    	}else{//获取html结构
    		return elem.innerHTML;
    	}
    }
    //事件
    Elem.prototype.on = function(type,fn){
    	var elem = this.elem;
    	elem.addEventListener(type,fn,false);
    	return this; //链式调用
    }
    

      调用:

    var div1 = new Elem('div1')
    
    div1.on('click',function(){
    	alert('clicked');
    })
    
    div1.html('点击');
    
    console.log(div1.html());
    

      

    instanceof 和 constructor

      检测某个对象是不是另一个对象的实例可以用constructor 或者instanceof

      1. instanceof的原理是:判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址(或者说是不是相等),如果是返回ture;如果是原型链上向上找的构造函数同样返回true。

      通过代码来解释:    

    var M = function (name) { this.name = name; };
    var o1 = new M('test');
    console.log(o1 instanceof M) //true
    console.log(o1 instanceof Object) //true

        因为o1.__proto__ === M.prototype 所以 o1 instanceof M 返回为true;

        因为 M.prototype.__proto__ === Object.prototype ,即Object是原型链上的构造函数,所以返回为true.

      2. constructor是:判断实例是由哪个构造函数生成的。

      通过代码来解释:

    var M = function (name) { this.name = name; };
    var o1 = new M('test');
    console.log(o1.__proto__.constructor === M) //true
    console.log(o1.__proto__.constructor === Object) //false

     题目一解答:如何准确判断一个变量是数组类型?

      用instanceof来判断一个变量是否是数组,代码示例:

    var arr =[];
    arr.instanceof Array //true;
    typeof arr //object
    

      

    new 运算符的原理

      当我们new一个实例对象时,JS执行时在内部做了很多工作,下面用伪代码模拟其工作流程:

    new Foo('name') => {
        var obj = {}; //创建一个空对象
    obj.__proto__ = Foo.prototype; //把obj的__proto__指向构造函数的原型对象(Foo.prototype),此时建立了obj的原型链 obj->Foo.prototype -> Object.prototype
       var result = Foo.call(obj,'name');//改变this指向 

      return typeof result === 'object'? result : obj //判断result类型是不是对象,是返回result,不是返回obj
    }

         1)创建一个空对象obj,该对象obj继承构造函数的原型(Foo.prototype)

        2) 将这个空对象的__proto__指向构造函数Foo的原型对象

        3)构造函数Foo被执行,在执行的时候,相应的参数会被传入,同时上下文(this)会被替换成obj

        4) 考察第三步的返回值result,如果无返回值或者返回一个非对象的值,则将obj作为新对象返回;否则将result作为新对象返回

      题目三解答:描述 new 一个对象的过程?

        1. 首先创建一个新对象{};

        2. 将构函数的作用域赋给新的对象向(因此 this指向了这个新创建的对象);

        3. 执行构造函数中的代码(为这个新对象添加属性);

        4. 返回这个新对象

        

  • 相关阅读:
    出现java.lang.NoClassDefFoundError: org/apache/commons/collections/FastHashMap错误问题解决
    选择一个更合适的编程语言
    23.if结构简单应用
    java环境的配置-传送门
    Java课程继续更新说明
    go语言熟知的开源项目
    go语言关于值类型和引用类型
    go语言实现生产者-消费者
    http协议——无连接、无状态
    jenkins结合gitlab实现提交代码自动构建
  • 原文地址:https://www.cnblogs.com/yangkangkang/p/8710683.html
Copyright © 2020-2023  润新知