zoukankan      html  css  js  c++  java
  • JavaScript基础知识——原型和原型链

    二、原型和原型链

    Q:1、如何准确判断一个变量是数组类型?

    var arr = [];
    arr instanceof Array; // true
    //反例
    typeof arr;// typeof不能判断arr是否是数组

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

    //封装一个DOM查询
    function Elem ( id ){
        this.elem = document.getElementById( id );
    }
    Elem.prototype.html = function( val ){
        var elem = this.elem;
        if ( val ){
            elem.innerHTML = val;
            return this;   //链式操作
        } else {
            return elem.innerHTML;
        }
    }
    
    Elem.prototype.on = function( type, fn ){
      var elem = this.elem;
      elem.addEventListener( type, fn );
      return this;  //链式操作
    }
    
    var div1 = new Elem('div1');
    // console.log(div1.html());
    // div1.html('<p>Hello</p>');
    // div1.on('click',function(){
    //   alert('clicked')
    // });
    div1.on('click',function(){alert('clicked')}).html('<p>链式操作</p>')
    //在之前的函数中增加了return this,由div1调用时便会返回当前对象,即div1,便可以实现链式操作

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

        a、创建一个新对象

        b、this指向这个新对象

        c、执行代码,即对this赋值

        d、最后返回this

      知识点:

        (1)、构造函数 

    function Foo (name, age) {
        this.name = name;
        this.age = age;
        this.class = 'class-2';
        // return this;// 默认有这一行
    }    
    var f = new Foo('张三',20);
    //当在执行new Foo()的时候,是先return 空this,然后会赋值this.name = '张三',this.age = 20
    console.log(f);//Foo {name: "张三", age: 20, class: "class-1"}
    console.log(f.name);//张三
    console.log(f.age);//20

        (2)、构造函数-扩展

    var a={}; //其实是var a=new Object()的语法糖
    var b=[]; //其实是var b=new Array()的语法糖
    function Foo(){...} //其实是var Foo=new Function(...)
    //使用instanceof判断一个函数是否是一个变量的构造函数

    所有的引用类型(对象、数组、函数)都有构造函数,a的构造函数是Object(),b的构造函数是Array(),Foo的构造函数是Function()。所以假如想要判断一个变量是否为数组就可以使用 var a = {}; a instanceof Array // false,更推荐var a = {};这种方式声明一个对象的方式

        (3)、原型规则(5条)和示例

        a、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)

    var obj={};obj.a=100;// obj可以扩展一个属性a
    var arr=[];arr.a=100;// arr可以扩展一个属性a
    function fn(){}
    fn.a=100;// fn可以扩展一个属性a

        b、所有引用类型(数组、对象、函数)都有一个__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__)

        c、所有的函数,都有一个prototype属性,属性值也是一个普通对象

        d、所有引用类型的__proto__属性值指向它的构造函数的prototype的属性值

    var obj={};obj.a=100;
    console.log( obj.__proto__ === Object.prototype );//true

        e、当试图得到 一个对象的某个属性时,如果这个对象本身没有这个属性,那么回去它的__proto__(即它的构造函数的prototype)中寻找。

    // 构造函数
    function Foo(name,age) {
      this.name = name;
      this.age = age;            
    }
    
    Foo.prototype.alertName = function () {
      alert(this.name);      
    }
    
    var f = new Foo('小明');
    f.printName = function () {
      console.log(this.name);  
    }
    
    f.alertName();//弹出提示框'小明'
    f.printName();//小明 f没有alertName属性,于是去f._proto_即Foo.prototype中查找

        由对象调用原型中的方法,this永远指向对象本身。  

      (4)循环对象自身的属性

    var item
    for(item in f){
        //高级浏览器已在for in中屏蔽了来自原型的属性
        //但是这里建议还是加上这个判断以保证程序的健壮性
        if(f.hasOwnProperty(item)){
            console.log(item)
        }
    }

      (6)原型链

    // 构造函数
    function Foo(name,age) {
      this.name = name;
      this.age = age;            
    }
    
    Foo.prototype.alertName = function () {
      alert(this.name);      
    }
    
    var f = new Foo('小明');
    f.printName = function () {
      console.log(this.name);  
    }
    
    f.alertName();//弹出提示框'小明'
    f.printName();//小明 f没有alertName属性,于是去f._proto_即Foo.prototype中查找
    f.toString();//要去f.__proto__.__proto__中查找
    所有的引用类型都有__proto__属性,且__proto__属性值指向它的构造函数prototype的属性值,所以当f不存在toString时,便会在f.__proto__Foo.prototype中查询,而Foo.prototype中也没有找到toString。由于Foo.prototype也是一个对象,所以它隐式原型__proto__的属性值便指向它的构造函数Object的prototype的属性值。

      (7)、instanceof

        用于判断引用类型属于哪个构造函数的方法
        f instanceof Foo的判断逻辑是f__proto__一层层向上能否对应到Foo.prototype,再试着判断f instanceof Object

  • 相关阅读:
    前端vscode比较好用的保存自动格式化settings.json配置
    jvm 调优
    ElasticSearch CPU和内存占用高的优化记录
    nginx 安装部署
    Windows 下Redis的部署 及key 过期事件
    Docker 部署应用过程记录
    实现鼠标悬停,div勾画div边框的动画
    html+jquery实现简单图片裁剪
    css+jquery 实现图片局部放大预览
    flex 布局 实现电商网页菜单的多级分类展示
  • 原文地址:https://www.cnblogs.com/utrustme/p/8548678.html
Copyright © 2011-2022 走看看