JS对象相关知识点

90 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

JS对象,面试必考知识点,面试难点,是工作中必须了解的知识点之一,话不多说,先自我总结一波,汇总一下自己的知识点

什么是对象?

ECMAScript 把对象定义为:无序属性的集合,其属性可以包含基本值对象或者函数

new做了什么?

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

总结:new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。

创建对象的方式有哪些?

  1. new Object()

    var person = new Object()
        person.name = 'rose'
        person.sayName = function () {
        console.log(this.name)
    }
    

    缺点:每次创建实例对象都要new比较麻烦,所以可以通过简写形式即对象字面量来创建。

  2. 对象字面量方法

    var person = {
        name: 'rose',
        sayName: function () {
            console.log(this.name)
        }
    }
    

    缺点:创建多个时代码太过冗余,重复性太高。

  3. 工厂模式

    function createPerson(name,age,family) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.family = family;
        o.say = function(){
        alert(this.name);
        }
        return o;
    }
    var person1 = createPerson("rose",21,["rose","rose","rose"]); 
    var person2 = createPerson("jack",18,["jack","jack","jack"]);
    console.log(person1 instanceof Object); //true
    

    工厂模式解决了重复实例化多个对象的问题,但是有一个对象识别的问题,本例中,得到的都是o对象,对象的类型都是Object,因此出现了构造函数模式

  4. 构造函数模式

        function Person(name,age,family) {
            this.name = name;
            this.age = age;
            this.family = family;
        this.say = function(){
            alert(this.name);
            }
        }
        var person1 = createPerson("rose",21,["rose","rose","rose"]); 
        var person2 = createPerson("jack",18,["jack","jack","jack"]);
        console.log(person1 instanceof Object); //true
        console.log(person1 instanceof Person); //true
        console.log(person2 instanceof Object); //true
        console.log(person2 instanceof Person); //true
        console.log(person1.constructor); //constructor
    

    调用构造函数步骤:

    1. 创建一个新对象
    2. 将构造函数的作用域赋给新对象(将this指向这个新对象)
    3. 执行构造函数代码(为这个新对象添加属性)
    4. 返回新对象 ( 指针赋给变量person )

    可以看出,构造函数知道自己从哪里来(通过 instanceof 可以看出其既是Object的实例,又是Person的实例)

    使用构造函数带来的最大的好处就是创建对象更方便了,但是其本身也存在一个浪费内存的问题。 那就是对于每一个实例对象, sayHello 都是一模一样的内容,把公共的函数拿出来免得每次生成实例都 为这些重复的内容浪费内存,就产生了原型模式。

  5. 原型模式
    把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上

     function Person(name) {
     }
     Person.prototype.name = 'jack';
     Person.prototype.getName = function () {
         console.log(this.name);
     };混合模式(构造函数模式+原型模式)
     
     var person1 = new Person();
    
     优点:方法不会重新创建
     缺点:1. 所有的属性和方法都共享 2. 不能初始化参数
    
  6. 混合模式(构造函数模式+原型模式)

        function Person(name,age) {
            this.name=name;
            this.age=age;
        }
        Person.prototype.eat=function () {
            console.log("123");
        };
        var p1=new Person("jack",20);
        var p2=new Person("rose",30);
        console.log(p1.eat==p2.eat);   //true
        console.dir(p1);
        console.dir(p2);
    

    优点:属性私有,方法共享,是目前使用最广泛的方式
    缺点:方法和属性没有写在一起,封装性不好。

如何判断一个对象是否属于某个类?

  1. instanceof 运算符来判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
  2. constructor 属性来判断,对象的constructor 属性指向该对象的构造函数,但是这种方式不是很安全,因为 constructor 属性可以被改写。
  3. Object.prototype.toString() 方法来打印对象的Class属性来进行判断。
  4. Object.getPrototypeof方法,先用这个方法获取实例对象的原型然后再与这个类进行比较

什么是深拷贝?深拷贝和浅拷贝有什么区别?

深拷贝和浅拷贝 在之前的文章中有总结过。

最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,如果原地址发生改变,那么浅拷贝出来的对象也会相应的改变。

深拷贝(deepCopy)是在计算机中开辟一块新的内存地址用于存放复制的对象。拷贝出来的对象与原来的对象互不影响,相互隔离

js监听对象属性的改变

  1. 在ES5中可以通过Object.defineProperty来实现已有属性的监听(vue2)
  2. 在ES6中可以通过Proxy来实现 (vue3)

具体它们的区别之后再单独总结一下。。。