构造函数
Q:是什么?
- A:专门用来生成实例对象的函数。
- JavaScript 语言使用构造函数(constructor)作为对象的模板。
Q:特点是什么?
- A:
- 函数体内部使用了
this关键字,代表了所要生成的对象实例。 - 生成对象的时候,必须使用
new命令。 - 构造函数名一般为大写字母开头
- 函数体内部使用了
Q:构造函数如何实现继承?
A:
方法一:构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上
javascriptfunction Animal(){ this.species = "动物"; } function Cat(name,color){ //继承Animal Animal.apply(this, arguments); this.name = name; this.color = color; } var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
方法二: prototype模式(常见)
若子类的prototype对象,指向一个父类的实例,那么所有子类的实例,就能继承父类了。
javascript//将子类的prototype对象,指向一个父类的实例 //它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。 Cat.prototype = new Animal(); //任何一个prototype对象都有一个constructor属性,指向它的构造函数。 //若没有这行,Cat.prototype.constructor指向Animal。 Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物注意:
如果替换了prototype对象,必需为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。
javascripto.prototype = {}; o.prototype.constructor = o;
方法三:直接继承prototype
- 先将子类
prototype指向父类prototype - 再改变子类构造函数
- 最后创建子类实例
javascriptfunction Animal(){ } Animal.prototype.species = "动物"; Cat.prototype = Animal.prototype; Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物- 优点:效率比较高(不用执行和建立父类的实例),比较省内存
- 缺点:子类
prototype和父类prototype都指向同一个对象(即:子类可以对父类的prototype进行修改)
- 先将子类
方法四: 利用空对象作为中介
javascriptfunction extend(Child, Parent) { //F是空对象,所以几乎不占内存。 var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; //意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。 //等于在子对象上打开一条通道,可以直接调用父对象的方法。 //为了实现继承的完备性,纯属备用性质。 Child.uber = Parent.prototype; } extend(Cat,Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物方法五:拷贝继承
- 把父对象的所有属性和方法,拷贝进子对象
javascript//将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。 function extend2(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; } extend2(Cat, Animal); var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
Q:如何给构造函数添加属性?
A:将属性添加至构造函数原型上。
javascript//✅ Person.prototype.getFullName = function () { return `${this.firstName} ${this.lastName}`; } //❌ Person.getFullName = function () { return `${this.firstName} ${this.lastName}`; }
Q:如何使用super实现继承
A:
javascriptclass Dog { constructor(name) { this.name = name; } }; class Labrador extends Dog { constructor(name, size) { super(name); this.size = size; } }- super相当于调用父类的构造函数,所传的参数,在父类构造函数中可以接受到。
new命令
Q:new使用时发生了什么?
A:执行构造函数,返回一个实例对象。相当于使用一个立即函数。每当用
new调用函数时,JavaScript 解释器都会在底层创建一个全新的对象并把这个对象当做this。- 首先创建一个空对象,然后赋值给this。
- 执行函数,通常修改this对象,增加一些新的属性。
this被返回。
javascriptfunction person(name) { this.name = name; } var foo = new person("deen"); //通过new创建了一个对象 //new是一种语法糖,new person等价于 var bar = (function(name) { var _newObj = { constructor : person, __proto__ : person.prototype, }; _newObj.constructor(name); // _newObj.constructor.call(_newObj, name) return _newObj; })();
Q:如果忘了使用new命令,直接调用构造函数会发生什么事?
A:构造函数就变成了普通函数,并不会生成实例对象。
this这时代表全局对象。javascriptvar Vehicle = function (){ this.price = 1000; }; var v = Vehicle(); v // undefined //price属性变成了全局变 price // 1000
Q:构造函数内部有return语句会发生什么?
A:
若return对象,则返回return指定的对象
javascriptvar Vehicle = function (){ this.price = 1000; return { price: 2000 }; }; (new Vehicle()).price // 2000注意:
- 如果
return语句返回的是一个跟this无关的新对象,new命令会返回这个新对象,而不是this对象。
- 如果
否则,就会不管
return语句,返回this对象。javascriptvar Vehicle = function () { this.price = 1000; return 1000; }; (new Vehicle()) === 1000 // false
Q:构造函数内部如何知道是否使用new指令?
A:可以使用
new.target属性。- 如果当前函数是
new命令调用,new.target指向当前函数 - 否则为
undefined。
javascriptfunction f() { console.log(new.target === f); } f() // false new f() // true- 如果当前函数是
对象
Q:是什么?
- A:每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。
- 对象是单个实物的抽象。
- 对象是一个容器,封装了属性(property)和方法(method)。
Q:有什么特征?
A:
可以复用,通过继承机制还可以定制。
如果你有两个名称相同的键,则键会被替换掉。它仍然位于第一个键出现的位置,但是值是最后出现那个键的值。
javascriptconst obj = { a: 'one', b: 'two', a: 'three' } console.log(obj) //{a:'three',b:'two'}
Q:如何访问对象中的属性?
A:
javascript//方法一 const value=obj.key; //方法二 const value=obj['key'];
Q:所有对象的键所属类型是啥?
所有对象的键(不包括 Symbol)在底层都是字符串。
javascriptconst obj = { 1: 'a', 2: 'b', 3: 'c' } obj.hasOwnProperty('1')//true obj.hasOwnProperty(1)//false
Q:如何判断一个对象是否拥有某一个属性/方法?
A:通过in来判断,无论是该属性/方法存在于实例对象还是原型对象。
javascriptfunction Person(name, age) { this.name = name; this.age = age; } Person.prototype.getName = function() { return this.name; } var p1 = new Person('tim', 10); console.log('name' in p1); // true
Q:当调用一个对象不存在的函数时,会抛出什么类型的错误?
- A:TypeError
Q:如何给对象添加一个新属性?
A:
方法一:
defineProperty方法。javascriptObject.defineProperty(targetObj, key, options);targetObj:修改的目标对象(object)key:键名(string)options:键名 描述 value 键值 writable 可写性 enumerable 可枚举性(默认为false) configurable
方法二:obj[key]
实例
Q:是什么?
- A:通过构造函数创建出来的对象。
instanceof
Q:能干啥?
- A:可以判断实例对象的__proto__属性是否与构造函数的prototype属性指向同一地址,是的话返回true,否则fasle。
静态方法
Q:特点是啥?
只能被创建它们的构造器使用,并且不能传递给实例。(即:不能被实例使用)
- 若被使用则抛出
TypeError错误。
javascriptclass Chameleon { static colorChange(newColor) { this.newColor = newColor return this.newColor } constructor({ newColor = 'green' } = {}) { this.newColor = newColor } } const freddie = new Chameleon({ newColor: 'purple' }) freddie.colorChange('orange')- 若被使用则抛出