最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 探索JavaScript对象构造函数都有哪些模式

    正文概述 掘金(蛙人)   2021-02-02   387

    为什么要出模式这概念,每个模式的出现都是解决一种问题,当然每个模式都是有利有弊的。
    模式它能干什么,它能帮助我们代码简洁,且更容易维护,代码不冗余。

    这里借用修言大佬的理解:

    工厂模式

    工厂模式在软件工程领域是一种广为人知的设计模式,这种模式抽象了创建对象的具体过程。
    该模式防止一个接口创建出很多对象,从而产生大量重复代码。

    function Person(name, age) {
        let o = new Object();
        o.name = name;
        o.age = age
        return o;
    }
    
    let person1 = Person("蛙人", 23)
    let person2 = Person("蛙人一号", 23)
    

    上面example中,可以无限的调用该函数,它每次都会返回2个属性,工厂模式虽然解决了创建多个相似对象的问题。但没有解决对象识别的问题,因为所有的实例都指向一个原型,然而又一个新模式诞生了。

    寄生构造函数模式

    这种模式的基本思想就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后在返回新创建的对象。

    function Person(name, age) {
        let o = new Object();
        o.name = name;
        o.age = age
        return o
    }
    

    上面example中,Person函数创建了一个新函数,新增了属性,最后又返回这个对象,这跟工厂函数是一模一样的, 一般不常用。

    构造函数模式

    js中构造函数可以用来创建特定类型的对象,像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。
    此外,也可以创建自定义构造函数,从而定义自定义对象类型和方法,使用构造函数将上面的example重写。

    function Person(name, age) {
        this.name = name;
        this.age = age
    }
    let person = new Person('蛙人', 23)
    

    上面example代码中和上面工厂模式代码不同之处在于

    1. 没有显示的创建对象
    2. 直接将属性和方法赋值给了this
    3. 没有return语句

    此外,构造函数必须写new操作符,那么new的过程发生了什么

    1. 在函数内部隐式的创建一个对象
    2. 将构造函数的作用域赋值个新对象(因此this就指向了这个对象)
    3. 执行函数中的代码,this.xxx 这时这个this就是该函数对象,就可以添加属性和方法啦
    4. 隐式的返回return this

    在上面person实例上有一个constructor属性,该属性指向Person函数实例

    console.log(person1.constructor == Person)
    

    constructor属性最初是作为对象的类型,我们可以还有instanceof来查看。

    console.log(person instanceof Object) // true
    console.log(person instanceof Person) // true
    

    instanceof是查看前者的是prototype属性是不是指向后者的prototype


    1. 将构造函数当做函数

    构造函数和普通函数的唯一区别,它们之间就是调用方式不同。不过构造函数也是函数,不存在特殊语法,任何函数只要通过new操作符来调用,那它就可以作为构造函数,反之,任何函数不通过new操作符来调用,那它跟普通函数也是一样的,上面的Person函数可以通过下列方式来调用。

    // 通过new操作符来调用
    let person = new Person('蛙人', 23)
    console.log(person.name) // 蛙人
    
    // 普通方式调用
    Person('蛙人', 23)
    console.log(window.name) // 蛙人
    
    // 在另一个作用域中调用
    let o = new Object()
    Person.call(o, '蛙人', 23)
    o.name
    

    2. 构造函数的弊端

    构造函数虽然好用,代码也不冗余。但是如果我们要在构造函数中定义方法,则需要在每个实例里面都创建一个,我们知道在js中函数也是对象,创建一个函数也是相当于初始化一个对象。看下列代码

    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function() {
        	return this.name
        }
    }
    function Animal() {
        this.name = name;
        this.weight = weight
        this.sayName = function() {
        	return this.name
        }
    }
    let person = new Person('蛙人', 23)
    let animal = new Animal('老虎', 120)
    console.log(person.sayName == animal.sayName) // false
    

    上面example中定义了两个实例,每个实例都有sayName方法,不同实例上,同名函数名是不相等的。我们觉得创建两个不同的同样的功能确实没必要,我们改写一下,把sayName函数挂载到全局作用域中。

    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = sayName
    }
    function Animal() {
        this.name = name;
        this.weight = weight
        this.sayName = sayName
    }
    function sayName() {
        return this.name
    }
    

    上面example中,我们把sayName函数定义在全局作用域中,两个实例现在就可以共享该方法,但是如果我们有多个共享函数,这样定义在全局作用域里面,就没有什么封装可言了。构造函数的弊端出现,又诞生了一个新的模式, 原型模式

    原型模式

    我们创建每个函数都会有一个prototype属性,这个属性是一个指针,指向一个对象。而这个对象的用途则可以包含特定的类型的所有共享实例和方法,new完实例之后,这个实例的原型对象(prototype)就是该函数实例,使用原型模式的好处是,可以让该实例共享它所包含的对象和方法,我们可以直接将方法和属性添加到对象的原型上。

    function Person() {}
    Person.prototype.name = "蛙人"
    Person.prototype.age = 23
    Person.prototype.sayName = function() {
        return this.name;
    }
    let person1 = new Person()
    console.log(person1.sayName()) // 蛙人
    let person2 = new Person()
    console.log(person1.sayName == person2.sayName) // true
    

    上面example中,我们访问的person1实例的属性和方法都是访问的原型对象上的, 如果构造函数中没有,就会去找该对象的原型上。

    1.理解原型对象

    无论什么时候,只要创建一个函数,该函数就会存在一个prototype属性,这个属性指向函数的原型对象,所有原型对象都会自动获得一个constructor构造函数属性,这个属性包含一个指向prototype属性所在函数的指针,也就是说这个prototype属性的主人是谁。

    创建一个空的自定义构造函数之后,其原型对象默认只会取得constructor属性,至于其它的属性和方法都是从Object继承而来,当调用构造函数之后,该函数内部包含一个指针(__proto__),指向构造函数的原型对象,js官方术语管这个叫做[[Prototype]],虽然没有明确标准方式访问[[Prototype]],但Firefox、Safari、Chrome在每个对象上都支持一个__proto__属性,不过最重要的一点是,这个属性__proto__指向构造函数的原型对象,而不是构造函数。

    探索JavaScript对象构造函数都有哪些模式
    图片来自js红宝书

    起源地下载网 » 探索JavaScript对象构造函数都有哪些模式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元