• JavaScript高程第三版笔记-面向对象编程


    之前有篇博客曾提到过一点js的面向对象编程:js面向对象编程.

    这里就结合js高程详细剖析一下javascript的面向对象编程.

    前序:

    1⃣️Object.defineProperty()

        var obj = {
          _name:'jack'
        };
        Object.defineProperty(obj,'name',{
          configurable:false,//表示能否通过delete删除属性从而重新定义属性,默认值true
          value:'orange',//属性的数据值,默认值undefined
          writable:false,//表示能否修改属性的值,默认值为true
          enumerable:false,//是否可枚举,能否通过for-in循环返回属性,默认值为true
          get:function(){//getter
            return this._name;
          },
          set:function(newval){//setter
            this._name = newval;
          }
        })

    vue2.x版本的双向数据绑定就是基于该API和订阅/发布模式实现的;

    如果同时定义多个属性,可通过如下API:

    Object.defineProperties(book, {
        _year: {
            value: 2004
        },
        edition: {
            value: 1
        },
        year: {
            get: function(){
                return this._year;
            },
            set: function(newValue){
                if (newValue > 2004) {
                    this._year = newValue;
                    this.edition += newValue - 2004;
                }
            }
    } });

    2⃣️读取属性的特性Object.getOwnPropertyDescriptor() 

    var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
    alert(descriptor.value); //2004
    alert(descriptor.configurable); //false

    正文:

    3⃣️创建对象

    3.1 工厂模式

    function createPerson(name, age, job){
            var o = new Object();
            o.name = name;
            o.age = age;
            o.job = job;
            o.sayName = function(){
                alert(this.name);
            };
            return o; 
    }
    var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");

    工厂模式创建了n个互不关联的对象,但是却没有解决对象识别的问题(即怎样知道一个对象的类型) .

    3.2 构造函数模式

    function Person(name, age, job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayName = function(){
                alert(this.name);
    }; }
    var person1 = new Person("Nicholas", 29, "Software Engineer");
    var person2 = new Person("Greg", 27, "Doctor");

    因为函数也是一个对象,所以可以通过该方式创建一个Person对象;

    按照惯例,构造函数始终都应该以一个 大写字母开头,而非构造函数则应该以一个小写字母开头 ;

    要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4 个步骤:

    (1) 创建一个新对象;
    (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
    (3) 执行构造函数中的代码(为这个新对象添加属性);
    (4) 返回新对象。

    alert(person1.constructor == Person); //true
    alert(person2.constructor == Person); //true
    alert(person1 instanceof Object);  //true
    alert(person1 instanceof Person);  //true
    alert(person2 instanceof Object);  //true
    alert(person2 instanceof Person);  //true

    构造函数模式虽然好用,但也并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍,不能共享。虽然我们可以将该方法写到全局作用域,然后在构造函数内部调用,但是这种做法显然耦合度过高.

    3.3 原型模式

    可以顺便参照之前的博客:js继承的实现.

    function Person(){
    }
    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
        alert(this.name);
    };
    var person1 = new Person();
    person1.sayName();   //"Nicholas"
    var person2 = new Person();
    person2.sayName(); //"Nicholas"
    alert(person1.sayName == person2.sayName);  //true

    可以看到,原型属性上的属性值和属性方法是被所有实例共享的.

    3.3.1实例属性和原型属性

    person1.name = "Greg";
    alert(person1.name);  //"Greg"——来自实例 
    alert(person2.name);  //"Nicholas"——来自原型

    delete person1.name; alert(person1.name); //"Nicholas"——来自原型

    我们看到访问实例属性的时候,优先级是实例属性-->原型属性,删除属性的时候优先级也是如此;

    实例上有该属性,就直接拿实例的该属性,没有的话就去原型上找.

    3.3.2 hasOwnProperty() 判断属性是不是来自于实例

    var person1 = new Person();
    var person2 = new Person();
    alert(person1.hasOwnProperty("name"));  //false
    person1.name = "Greg";
    alert(person1.name); //"Greg"——来自实例 
    alert(person1.hasOwnProperty("name")); //true

    实例的原型属性不可枚举:

    var keys = Object.keys(Person.prototype);
    alert(keys);       //"name,age,job,sayName"

    var p1 = new Person(); p1.name = "Rob"; p1.age = 31; var p1keys = Object.keys(p1); alert(p1keys); //"name,age"
  • 相关阅读:
    js 数组相减
    js 对象数组去重
    vue 首次不触发watch的解决方法
    "神药"推荐--紫花地丁
    openstack 平台添加 nvidia vGPU
    string易错点整理总结
    CentOS安装图形界面
    CentOs安装ssh和scp
    数组把0移到末尾
    Windows下Celery安装与下使用
  • 原文地址:https://www.cnblogs.com/eco-just/p/11326508.html
Copyright © 2020-2023  润新知