• 构造函数用途及优缺点


    每个对象上面都有一个constructor属性( 严格意义上来说,是原型上的,对象是通过查找到原型找到 constructor属性 ).后面讲到原型的时候,我会用示意图的方式说明。

     1         function CreateObj(uName) {
     2             this.userName = uName;
     3             this.showUserName = function () {
     4                 return this.userName;
     5             }
     6         }
     7         var obj1 = new CreateObj('ghostwu');
     8         var obj2 = new CreateObj('卫庄');
     9         console.log( obj1.constructor === CreateObj ); //true
    10         console.log( obj2.constructor === CreateObj ); //true

    默认情况下,对象的constructor等于实例化对象的构造函数, constructor最初的作用是用来标识对象的,但是并不是特别准确,因为constructor能被修改,

    识别对象一般用instanceof关键字.

    什么是instanceof?

    要理解这个关键字,需要搞清楚原型链,这里,我提前把他放出来。

    //假设instanceof运算符左边是L,右边是R
    L instanceof R 
    //instanceof运算时,通过判断L的原型链上是否存在R.prototype
    L.__proto__.__proto__ ..... === R.prototype ?
    //如果存在返回true 否则返回false

    注意:instanceof运算时会递归查找L的原型链,即L.__proto__.__proto__.__proto__.__proto__...直到找到了或者找到顶层为止。

    所以一句话理解instanceof的运算规则为:

    instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型。

     console.log( obj1 instanceof Object ); //true
     console.log( obj2 instanceof Object ); //true
     console.log( obj1 instanceof CreateObj ); //true
     console.log( obj2 instanceof CreateObj ); //true

    obj1,obj2之所以是Object的实例,因为所有对象继承自Object

    借用构造函数

    一个空对象,可以借用现有的构造函数,完成属性和方法的复制。

    function CreateObj(uName) {
                this.userName = uName;
                this.showUserName = function () {
                    return this.userName;
                }
            }
            var obj = new Object();
            CreateObj.call( obj, 'ghostwu' );
            console.log( obj.userName ); //ghostwu
            console.log( obj.showUserName() ); //ghostwu

    构造函数的优点与缺点

    优点就是能够通过instanceof识别对象,缺点是每次实例化一个对象,都会把属性和方法复制一遍

    1         var obj1 = new CreateObj('ghostwu');
    2         var obj2 = new CreateObj('卫庄');
    3 
    4         console.log( obj1.showUserName === obj2.showUserName ); //false

    从以上执行结果,可以看出obj1.showUserName和obj.showUserName不是同一个【在js中,引用类型比较的是地址, 函数是一种引用类型】,而是存在两个不同
    的内存地址,因为每个对象的属性是不一样的,这个没有什么问题,但是方法执行的都是一样的代码,所以没有必要复制,存在多份,浪费内存.这就是缺点

    怎么解决构造函数的方法复制多次的问题?

    function CreateObj(uName) {
                this.userName = uName;
                this.showUserName = showUserName;
            }
            function showUserName (){
                return this.userName;
            }
            var obj1 = new CreateObj('ghostwu');
            var obj2 = new CreateObj('卫庄');
            console.log( obj1.showUserName === obj2.showUserName ); //true

    把对象的方法指向同一个全局函数showUserName, 虽然解决了多次复制问题,但是全局函数非常容易被覆盖,也就是大家经常说的污染全局变量.

    比较好的解决方案?

    通过原型(prototype)对象,把方法写在构造函数的原型对象上

    function CreateObj(uName) {
                this.userName = uName;
            }
            CreateObj.prototype.showUserName = function(){
                return this.userName;
            }
            var obj1 = new CreateObj('ghostwu');
            var obj2 = new CreateObj('卫庄');
            console.log( obj1.showUserName === obj2.showUserName );      //true
  • 相关阅读:
    AES加解密
    redis HyperLogLog使用
    vi常用操作
    redis string使用
    用jdk命令定位java应用问题
    用户态、内核态及零拷贝
    缓存穿透与雪崩
    ReentrantLock、Semaphore、AQS
    redis list使用
    不同数据库取并集、交集、差集
  • 原文地址:https://www.cnblogs.com/art-poet/p/12112450.html
Copyright © 2020-2023  润新知