【JavaScript】10. 对象与原型

239 阅读3分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

01. 对象

  • 创建对象的方式:字面量创建、new Object()创建、构造函数创建

    • 字面量创建

      let ruovan = {
          name: 'ruovan',
          age: '24',
          say: function(){
              console.log('hello')
          }
      }
      
    • new Object()创建

      let ruovan = new Object()
      ruovan.name = 'ruovan'
      ruovan.age = 24
      ruovan.say = function(){
          console.log('hello')
      }
      
    • 构造函数创建

      function Person(name, age){
          this.name = name
          this.age = age
          this.say = function(){
              console.log('hello,' + this.name)
          }
      }
      
      let ruovan = new Person('ruovan', 24)
      

02. 构造函数

  • 所谓构造函数,就是一个用来构造对象的函数

    • Object、String、Number等其实都是构造函数,都可以通过new的方式来得到实例对象
  • 一般情况下:

    • 构造函数搭配new使用
    • 构造函数的首字母大写
    • 构造函数不需要 return
  • 使用构造函数创建对象时,new 在执行时会做四件事情:

    • 在内存中创建一个新的空对象
    • 将构造函数里的this指向这个新的对象
    • 执行构造函数里面的代码,为这个新对象添加属性和方法,并赋值为传递进来的参数
    • 返回这个新对象
  • 手写new

    function create () {
        // 1. 创建一个新的空对象
        var obj = new Object();
        
        // 2. 取出第一个参数, 就是我们要传入的构造函数; 同时arguments会被去除第一个参数
        Con = [].shift.call(arguments);
        
        // 3. 将 obj的原型指向构造函数,这样obj就可以访问到构造函数原型中的属性
        obj.__proto__ = Con.prototype;
        
        // 4. 使用apply,改变构造函数this 的指向到新建的对象,这样 obj就可以访问到构造函数中的属性
        var ret = Con.apply(obj, arguments);
        
        // 5. 优先返回构造函数返回的对象
        return ret instanceof Object ? ret : obj;
    }
    
    

需要注意到:

  • 通过构造函数创建的对象,其实例的方法不一样(但应该是一样的)

因此,需要将构造函数的方法设置在其原型上


03. 原型

  • 每个函数都有一个prototype属性——即原型

    • 这个属性是一个指针,它指向一个对象,这个对象就是这个函数的原型对象
    • 这个原型对象可以用来共享所有实例的属性和方法,即是所有实例公用的
    // 上述构造函数可以这样写
    function Person(name, age){
        this.name = name
        this.age = age
    }
    
    Person.prototype.say = function(){
        console.log('hello,' + this.name)
    }
    
    let ruovan = new Person('ruovan', 24)
    let composition = new Person('composition', 24)
    
    ruovan.say() == composition.say() // true
    
    
  • 每个实例对象都有一个__proto__属性

    • 这个属性也是一个指针,它指向一个对象,这个对象是实例对象的构造函数的原型对象
      • 即: ruovan.__proto__ == Person.prototype
  • 每个原型对象都有一个constructor属性

    • 这个属性指向的是构造函数本身
      • 即: Person.prototype.constructor == Person
  • 每个原型对象也是一个对象,那么原型对象也将会有一个__proto__属性

    • 这个原型对象的__proto__属性将指向Object的原型对象
      • 即: Person.prototype.__proto__ == Object.prototype
    • Object的原型对象的__proto__属性将指向null

当实例对象要访问某个属性或者方法,会先从自身上找;

如果没有,则在其__proto__属性上找;

如果还没有.则向更上一级的__proto__属性上找;

直到找到Null


  • 特别的Function

    Object instanceof Function 		// true
    Function instanceof Object 		// true
    
    Object instanceof Object 			// true
    Function instanceof Function 	// true
    
    • 可以看到

      • Function是一个构造函数,所以它有原型对象:Function.prototype

      • Function还是一个对象,所以它有对象原型:Function.__proto__

      Function.__proto__ === Function.prototype // true
      
    • 只有函数才有prototype属性,但并不是所有函数都有这个属性


本人前端小菜鸡,如有不对请谅解