本文已参与「新人创作礼」活动,一起开启掘金创作之路。
JS对象,面试必考知识点,面试难点,是工作中必须了解的知识点之一,话不多说,先自我总结一波,汇总一下自己的知识点
什么是对象?
ECMAScript 把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。
new做了什么?
- 首先创建了一个新的空对象
- 将构造函数的作用域赋值给这个新的对象(因此this指向了这个新的对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
总结:new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。
创建对象的方式有哪些?
-
new Object()var person = new Object() person.name = 'rose' person.sayName = function () { console.log(this.name) }缺点:每次创建实例对象都要new比较麻烦,所以可以通过简写形式即对象字面量来创建。
-
对象字面量方法
var person = { name: 'rose', sayName: function () { console.log(this.name) } }缺点:创建多个时代码太过冗余,重复性太高。
-
工厂模式
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,因此出现了构造函数模式
-
构造函数模式
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调用构造函数步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(将this指向这个新对象)
- 执行构造函数代码(为这个新对象添加属性)
- 返回新对象 ( 指针赋给变量person )
可以看出,构造函数知道自己从哪里来(通过 instanceof 可以看出其既是Object的实例,又是Person的实例)
使用构造函数带来的最大的好处就是创建对象更方便了,但是其本身也存在一个
浪费内存的问题。 那就是对于每一个实例对象, sayHello 都是一模一样的内容,把公共的函数拿出来免得每次生成实例都 为这些重复的内容浪费内存,就产生了原型模式。 -
原型模式
把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上function Person(name) { } Person.prototype.name = 'jack'; Person.prototype.getName = function () { console.log(this.name); };混合模式(构造函数模式+原型模式) var person1 = new Person(); 优点:方法不会重新创建 缺点:1. 所有的属性和方法都共享 2. 不能初始化参数 -
混合模式(构造函数模式+原型模式)
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);优点:属性私有,方法共享,是目前使用最广泛的方式
缺点:方法和属性没有写在一起,封装性不好。
如何判断一个对象是否属于某个类?
- instanceof 运算符来判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
- constructor 属性来判断,对象的constructor 属性指向该对象的构造函数,但是这种方式不是很安全,因为 constructor 属性可以被改写。
- Object.prototype.toString() 方法来打印对象的Class属性来进行判断。
- Object.getPrototypeof方法,先用这个方法获取实例对象的原型然后再与这个类进行比较
什么是深拷贝?深拷贝和浅拷贝有什么区别?
深拷贝和浅拷贝 在之前的文章中有总结过。
最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,如果原地址发生改变,那么浅拷贝出来的对象也会相应的改变。
深拷贝(deepCopy)是在计算机中开辟一块新的内存地址用于存放复制的对象。拷贝出来的对象与原来的对象互不影响,相互隔离
js监听对象属性的改变
- 在ES5中可以通过Object.defineProperty来实现已有属性的监听(vue2)
- 在ES6中可以通过Proxy来实现 (vue3)
具体它们的区别之后再单独总结一下。。。