美文网首页
Js面向对象进阶

Js面向对象进阶

作者: Speng | 来源:发表于2019-03-01 11:41 被阅读0次

    一.普通对象与函数对象

    js中万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。下面举例说明

    var o1 = {}; 
    var o2 = new Object();
    var o3 = new f1();
    
    function f1(){}; 
    var f2 = function(){};
    var f3 = new Function('fn','console.log(fn)');
    
    console.log(typeof Object); //function 
    console.log(typeof Function); //function  
    
    console.log(typeof f1); //function 
    console.log(typeof f2); //function 
    console.log(typeof f3); //function   
    
    console.log(typeof o1); //object 
    console.log(typeof o2); //object 
    console.log(typeof o3); //object
    

    在上面的例子中 o1 o2 o3 为普通对象,f1 f2 f3 为函数对象。
    怎么区分,其实很简单,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。
    Function Object 最后是通过 New Function()创建的。

    二.构造函数

    function Person(name, age, job) {
       this.name = name;
       this.age = age;
       this.job = job;
       this.sayName = function() { alert(this.name) } 
    }
    var person1 = new Person('张三', 18, '搬砖');
    var person2 = new Person('李四', 18, '和泥');
    

    上面的例子中 person1 和 person2 都是 Person 的实例。
    这两个实例都有一个 constructor (构造函数)属性,该属性(是一个指针)指向 Person。

    console.log(person1.constructor == Person); //true
    console.log(person2.constructor == Person); //true
    

    记住两个概念(构造函数、实例):

    person1 和 person2 都是 构造函数 Person 的实例

    公式:

    实例的构造函数属性(constructor)指向构造函数

    三. 原型对象

    在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。

    function Person() {}
    Person.prototype.name = '张三';
    Person.prototype.age  = 18;
    Person.prototype.job  = '搬砖';
    Person.prototype.sayName = function() {
      alert(this.name);
    }
    var person1 = new Person();
    person1.sayName(); // '张三'
    
    var person2 = new Person();
    person2.sayName(); // '张三'
    
    console.log(person1.sayName == person2.sayName); //true
    

    上图中可以知道,实例__protpo__指向的是原型对象。
    实例的构造函数的prototype也是指向的原型对象。
    原型对象的construor指向的是构造函数。

    牢记!以下四条:

    1.每个对象都具有一个名为 __proto__的属性;
    2.每个构造函数都具有一个名为prototype的方法;
    3.每个对象的__proto__属性指向自身构造函数的prototype;
    4.每个对象都有__proto__属性,但只有函数对象才有 prototype 属性

    四、原型链

    简单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

    原型对象和实例之间有什么作用

    通过一个构造函数创建出来的多个实例,如果都要添加一个方法,给每个实例去添加并不是一个明智的选择。这时就该用上原型了。
    在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。

    var Met = function (name) { this.name = name; }
    var met = new Met('met')
    var met1 = new Met()
    met.__proto__.say=furnction(){
       console.log('hello world')
    }
    met.say()
    met1.say()
    

    按照JS引擎的分析方式,在访问一个实例的属性的时候,现在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到。这就是原型链。

      Met.__proto__===Function.prototype //true
    

    只有函数有prototype,对象是没有的
    但是函数也是有__proto__的,因为函数也是对象。函数的__proto__指向的是Function.prototype。也就是说普通函数是Function这个构造函数的一个实例。
    instanceof原理


    instanceof是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址。
    注意:实例的instanceof在比较的时候,与原型链上向上找的的构造函数相比都是true
    met.__proto__===Met.prototype//true
    met instanceof Met //true
    Met.prototype===Object.prototype//false
    Met.prototype.__proto__===Object.prototype//true
    met instanceof Object //true
    met.__proto__.constructor===Met//true
    met.__proto__.constructor===Object//fasle
    

    new运算符的原理

    1.一个新对象被创建。它继承自foo.prototype。
    2.构造函数返回一个对象。在执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新的实例。
    3.new foo等同于new foo(), 只能用在不传递任何参数的情况
    4.如果构造函数反悔了一个对象,那个这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那个new出来的结果为步骤1创建的对象。

    相关文章

      网友评论

          本文标题:Js面向对象进阶

          本文链接:https://www.haomeiwen.com/subject/nxswyqtx.html