JS知识点回顾(1)(原型/原型链/构造函数/实例/继承,数据类型判断,闭包(作用域,作用域链),Ajax的原生写法,对象深拷贝和浅拷贝)

221 阅读4分钟

原型/原型链/构造函数/实例/继承

  • 凡是构造函数都有一个原型属性prototype

    凡是对象都有一个原型,通过__proto__可以访问原形,访问到的原型又是对象,那么如此下去,就会构成一个对象的序列,该结构称为原型链

    默认的原型链就是: 当前对象-->构造函数.prototype-->Object.prototype--null

    注意: 原型和实例上都有一个constructor构造器指向构造函数 Function.prototype.constructor === new Function().constructor

  • 混合继承

    • 构造函数继承:apply/call继承构造函数里面的属性和方法

      const Person=function(name,age,sex){
                  this.name=name;
                  this.age=age;
                  this.sex=sex;
      }
      const Student=function(name,age,sex,pro){
                  //this:实例对象
                  Person.apply(this,arguments);//子类继承父类上面所有的属性和方法
                  this.pro=pro;
      }
      Student.prototype=Person.prototype;//引用传递       
      
    • 原型继承

      • 拷贝继承:原型是对象属性,浅拷贝的方式将父类原型上面的内容传递给子类。

        const Person=function(name,age,sex){
                    this.name=name;
                    this.age=age;
                    this.sex=sex;
        }
        const Student=function(name,age,sex,pro){
                    //this:实例对象
                    Person.apply(this,arguments);//子类继承父类上面所有的属性和方法
                    this.pro=pro;
        }
        Object.assign(Student.prototype,Person.prototype);
        
      • 原型链继承:将父类的实例给子类的原型

        Student.prototype=new Person();
        

        缺点:父类将子类的构造函数覆盖了。

        Student.prototype.constructor=Student;//重置构造函数
        
    • class继承

      • class person {
                    constructor(name, age, sex) { //构造函数
                        this.name = name;
                        this.age = age;
                        this.sex = sex;
                    }
        
                    singing() {
                        return `我的姓名是${this.name},我的年龄是${this.age},我是${this.sex}的`;
                    }
                }
        
        
                class student extends person{
                    constructor(name,age,sex,pro){
                        super(name,age,sex);//父类 当做函数使用,代表父类的构造函数。
                        this.pro=pro;
                    }
                }
        
        1. super当作函数调用时,继承父类的构造函数
        2. super作为对象时,在普通方法中指向父类的原型对象

数据类型判断

  • typeof

    • typeof 'a'; // string 有效
      typeof 1; // number 有效
      typeof true; //boolean 有效
      typeof Symbol(); // symbol 有效
      typeof undefined; //undefined 有效
      typeof new Function(); // function 有效
      typeof null; //object 无效
      typeof [1] ; //object 无效
      typeof new RegExp(); //object 无效
      typeof new Date(); //object 无效
      
      • 对于基本类型,除 null 以外,均可以返回正确的结果。
      • 对于引用类型,除 function 以外,一律返回 object 类型。
      • 对于 null ,返回 object 类型。
      • 对于 function 返回 function 类型。
  • instanceof

    • [] instanceof Array; // true
      new Date() instanceof Date;// true
       
      function Person(){};
      new Person() instanceof Person;//true
       
      [] instanceof Object; // true
      new Date() instanceof Object;// true
      new Person instanceof Object;// true
      
      • instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型
      • 需要通过new关键字 对对象进行判断
      • 对null和undefined判断时报错
  • constructor

    • 		var num = 12;
              console.log([].constructor); //Array
              console.log('string'.constructor); //string
              console.log(num.constructor); //number
              console.log(new Object().constructor); //object
      
      • 对null和undefined判断时报错
  • toString

    • 语法:Object.prototype.toString.call(value);

    • Object.prototype.toString.call('') ;   // [object String]
      Object.prototype.toString.call(1) ;    // [object Number]
      Object.prototype.toString.call(true) ; // [object Boolean]
      Object.prototype.toString.call(Symbol()); //[object Symbol]
      Object.prototype.toString.call(undefined) ; // [object Undefined]
      Object.prototype.toString.call(null) ; // [object Null]
      Object.prototype.toString.call(new Function()) ; // [object Function]
      Object.prototype.toString.call(new Date()) ; // [object Date]
      Object.prototype.toString.call([]) ; // [object Array]
      Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
      Object.prototype.toString.call(new Error()) ; // [object Error]
      Object.prototype.toString.call(document) ; // [object HTMLDocument]
      Object.prototype.toString.call(window) ; //[object global] 
      window 是全局对象 global 的引用
      

闭包(作用域,作用域链)

  • 主要作用:变量私有化,读取自身函数外部的变量(沿着作用域链寻找)
  • 缺点:
    • 闭包会让函数内部变量始终保存在内存中,需要手动释放资源;【解决办法:即将函数设置为null】
    • 过多的闭包导致内存泄漏。
  • 作用域:局部和全局,(ES6之后有块级作用域的概念)

Ajax的原生写法

  1. 新建ajax对象

    let ajax = new XMLHttpRequest();
    
  2. ajax对象的open()

    ajax.open('get','http://localhost/HTML1909/JS1909/Day%2021/5.phparray.php',true);
    //open(请求方式get/post,接口地址,是否异步true异步/false同步)
    
  3. ajax对象的send()

    ajax.send();
    
  4. ajax对象的事件--onreadystatechange监听就绪状态是否完成。

    ajax.onreadystatechange=function(){
                if(ajax.readyState===4){//请求完成
                //ajax.responseText:ajax请求返回的内容就被存放到这个属性下面,返回获取的内容,string	
                    console.log(ajax.responseText);
                    console.log(JSON.parse(ajax.responseText));
                }
            }
    
  • 如果是post还需要在open()后设置请求头

    xmlhttp.setRequestHeader("content-type", "application/x-www-form-urlencoded")
    

对象深拷贝和浅拷贝

  • 浅拷贝

    • Object.assign()

      语法:Object.assign(target ,source);

      var target = {};
      var source = {a:1};
      Object.assign(target ,source);
      console.log(target); //{a:1}
      source.a = 2;
      console.log(source); //{a:2}
      console.log(target); //{a:1}
      
    • 扩展运算符

      语法:var obj2 = {...obj};

      var obj = {a:1,b:{c:1}}
      var obj2 = {...obj};
      obj.a=2;
      console.log(obj); //{a:2,b:{c:1}}
      console.log(obj2); //{a:1,b:{c:1}}
      
      obj.b.c = 2;
      console.log(obj); //{a:2,b:{c:2}}
      console.log(obj2); //{a:1,b:{c:2}}
      
  • 深拷贝

    • JSON.stringify(JSON.parse())

      var obj1 = {
          a:1,
          b:[1,2,3]
      }
      var str = JSON.stringify(obj1)
      var obj2 = JSON.parse(str)
      console.log(obj2); //{a:1,b:[1,2,3]}
      obj1.a=2
      obj1.b.push(4);
      console.log(obj1); //{a:2,b:[1,2,3,4]}
      console.log(obj2); //{a:1,b:[1,2,3]}
      
    • 递归

      var obj1 = {
          a:{
              b:1
          }
      };
      function deepClone(obj) {
          var cloneObj = {}; //在堆内存中新建一个对象
          for(var key in obj){ //遍历参数的键
             if(typeof obj[key] ==='object'){ 
                cloneObj[key] = deepClone(obj[key]) //值是对象就再次调用函数
             }else{
                 cloneObj[key] = obj[key] //基本类型直接复制值
             }
          }
          return cloneObj 
      }
      var obj2 = deepClone(obj1);
      obj1.a.b = 2;
      console.log(obj2); //{a:{b:1}}