美文网首页
#JS续:2.1面向对象、原型

#JS续:2.1面向对象、原型

作者: 饥人谷_远方 | 来源:发表于2018-09-01 14:13 被阅读0次

    前言

    是的,面向对象和原型(链)也是一度让我陷入难以理解的边缘,不过我没有停留太久,直接跳过,做了项目,加上看了老师们的知乎文章之后,今天终于输出了对面向对象、prototype__proto__的理解,过程中可能啰嗦,whatever,同步和老师做完了题目之后,蜜汁自信又回来了哈哈哈哈😂~

    一、JS对象

    1、什么是对象

    JS 中的对象:是一系列无序 key: value 的集合

    先看下面这个代码:

    var obj = { a: 1, b: 2}   //json对象。字面量创建的对象
    var person = {
        name: 'hunger',
        sayName: function(){
            console.log('My name is hunger')
        }  //sayName对应的值是一个函数
    }
    

    2、获取对应属性的值

    通过 对象.属性来获取对应属性的值

    console.log(person.name)
    person.sayName()
    

    (1)那么,函数是一个对象?

    function sum(a, b){
        return a + b
    }
    

    如图:使用 函数名(对象).属性 进行查看该对象属性是否有值

    image

    总结:函数也是一个JS对象

    (2)同理,数组是对象?
    a = [1,2,3]
    如图:

    image
    总结:数组也是一个JS对象

    二、面向对象编程

    1、传统面向编程

    wiki的解释
    OOP(),是一种编程思路或编程方法,基于一个对象,该对象包含数据(一般即属性),以及一些执行过程的代码(即方法)。对象的方法,可以从外部去访问,并且可以去修改,调用此方法去修改对象的数据

    (1)面向过程的写法

    拧钥匙()
    联通电路()
    火花塞点火()
    活塞运动()
    内燃机启动()
    司机挂挡()
    变速箱工作()
    踩油门()
    活塞运动加快()
    刹车解除()
    连杆传输动力到轮子()
    轮子运转()
    

    面向过程的思路:一次性实现所有的流程

    (2)面向对象的写法

    Car.拧钥匙()
    Car.挂挡()
    Car.踩油门()
    

    面向对象的思路:把某个功能看成一个整体(对象),通过调用对象(如开车)的某个方法来启动功能。在用的时候不去考虑这个对象内部的实现细节,在去实现这个对象细节的时候不用管谁在调用

    2、构造一个对象

    比如我们用字面量构造了,暴露了这个对象的具体实现方法的细节:

    var obj1 = {
        nick: 'Byron',
        age: 20,
        printName: function(){
            console.log(obj1.nick);
        }
    }
    
    var obj2 = {
        nick: 'Casper',
        age: 25,
        printName: function(){
            console.log(obj2.nick);
        }
    }
    

    问题:这样构造有两个明显问题

    • 太麻烦了,每次构建一个对象都是复制一遍代码
    • 如果想个性化,只能通过手工赋值,使用者必需了解对象详细使用函数做自动化
    function createObj(nick, age){
      var obj = {
          nick: nick,
          age: age,
          printName: function(){
                console.log(this.nick);
            }
      };
      return obj;
    }
    
    var obj3 = createObj('Byron', 30);//创造一个对象去赋值对应参数
    obj3.printName();
    

    问题:这种方法解决了构造过程复杂,需要了解细节的问题,但是构造出来的对象类型都是Object,没有识别度

    3、New一个对象

    一个函数中含有要调用的对象共同属性,然后声明多个对象,就能相对应地调用函数对象中的属性值

    function people(name,age){
             this.name=name
             this.age=age
    }
    var obj1 = new people(hunger,2)
    var obj2 = new people(nick,10)
    

    以上代码的执行过程如下:

    (1)执行 new People

    • 创建一个空对象 {},假设名字是 tmpObj,这里实际上是new person
    • 执行 People 函数,执行过程中对 this 操作就是对 tmpObj 进行操作
    • 函数执行完后返回刚刚创建的 tmpObj

    (2)把 tmpObj 赋值给 obj1和obj2 ( obj1和obj2也指向同一个对象)

    ↓↓

    当你在写一个new对象的表达式时,其实就是在写一个构造函数,如写函数F时,都会自动添加prototype属性,这是一个对象new一个对象,创建一个空对象,这个对象中的内部属性__proto__指向这个函数类的prototype,执行函数时,初始化this(初始化this实质上也是给空对象初始化,然后函数return出这个已初始化的对象(实例),然后再把实例整体地赋值给一个变量,如p

    ↑↑

    4、构造函数

    • 任何函数使用new表达式就是构造函数
    • 每个函数都自动添加一个名称为prototype属性,这是一个对象
    • 每个对象都有一个内部属性__proto__(规范中没有指定这个名称,但是浏览器都这么实现的) 指向其类型的prototype属性,类的实例也是对象,其(指实例)__proto__属性指向“类”的prototype

    5、prototype

    原型,是可以把一些公共属性放在里面。这里的可以考虑放入的公共属性就可以默认参数


    image

    分析原型图:

    • 任何函数只要声明,就有prototype这个属性,也是一个对象,对象中含有constructor和proto
    • 如果调用:函数名.prototype.constructor,指的也还是这个函数
    • 函数中的prototype是一个对象,说明可以赋值,增加一些属性
    • 如果通过函数去创建一个新的空对象,就会在这个新对象中出现:proto,而这个属性则是指向了函数中的prototype这个对象,假如:

    p1.proto=函数中的prototype
    p2.proto=函数中的prototype

    • 说明,实例中的某些属性可以通过prop访问到其类型的prototype属性,这就意味着类的prototype对象可以作为一个公共容器,供所有实例访问。

    我们刚才的问题可以通过这个手段解决:

    • 所有实例都会通过原型链引用到类型的prototype
    • prototype相当于特定类型(函数)所有实例都可以访问到的一个公共容器
    • 重复的东西移动到公共容器里放一份就可以了

    看一下的代码:

    function Person(nick, age){
        this.nick = nick;
        this.age = age;
    }
    Person.prototype.sayName = function(){
        console.log(this.nick);
    }
    
    var p1 = new Person();
    p1.sayName();
    

    这里我们将一个共有属性sayName加入了函数中的prototype,即

    Person.prototype.sayName = function(){
        console.log(this.nick);
    }
    

    实例就可以从这个公共容器中设定的属性找到重复的公共属性值。

    相关文章

      网友评论

          本文标题:#JS续:2.1面向对象、原型

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