一. 构造函数
任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要功能为初始化对象。
对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。
1. 什么是构造函数?
在JS中用 new 关键字来实例化对象的函数,称为构造函数
2. 为什么需要 或者说会出现这个东西?解决什么问题?
在使用对象字面量创建一系列同一类型的对象时,这些对象可能具有一些相似的特征(属性)和行为(方法),此时会产生很多重复的代码,而使用构造函数就可以实现代码的复用。
3. 构造函数的执行过程
当一个函数创建好以后,我们并不知道它是不是构造函数,即使一般情况下构造函数首字母会大写。 只有当一个函数以 new 关键字来调用的时候,我们才能说它是一个构造函数。
1). 当以 new 关键字调用时,会创建一个新的内存空间,标记为该构造的实例。
2). this指向的就是新的内存空间,并执行构造函数内部代码,给实例增加属性
3). 返回this
4. 构造函数的返回值 默认为this
一般情况下不需要 手动添加 return 返回值。
当特殊情况发生,return一个基本类型变量时,返回值仍然是 this ; return 一个复杂数据类型时,返回值是该复杂数据类型。
二. 显式原型和隐式原型
- 每个函数function都有一个prototype,即显式原型
- 每个实例对象都有一个__proto__,可称为隐式原型
- 对象的隐式原型的值为其对应构造函数的显式原型的值
- 内存结构图
5. 总结:
* 函数的prototype属性,在定义函数时自动添加的,默认值是一个空Object对象
* 对象的__proto__属性,在创建对象时自动添加的,默认值为构造函数的prototype属性值
* 程序员能直接操作显式原型,但不能直接操作隐式原型(es6之前)
3.原型链
- 访问一个对象的属性时
- 先在自身属性中查找,找到返回
- 如果没有再沿着__proto__这条链向上查找,找到返回
- 如果最终没找到,返回undefined
4.显式原型,隐式原型,构造函数之间关心图
5. 原型链补充
函数的显式原型指向的是空Object,默认空。也可以说是Object的实例对线。(但是Object不满足,Object.prototype=null)
` Fn.prototype instanceof Object //true
Object.prototype instanceof Object //false
Function.prototype instaceof Object //true(所有函数都是Function的实例。同时Function是他自身的实例)
Function.__proto__ === Function.prototype //true
//Object的原型对象是原型链的尽头
Object.prototype.__proto__ === null //true
`
6. A instanceof B 判断也与原型链有关。
表达式:A instanceof B 判断A是属于B的实例。 当B函数对象的显式原型在A对象的隐式原型链上 返回true,否则false Function是New自己产生的实例。
7. 超级重要的2个原型链的测试题
`
function Foo(){}
Foo.prototype.name = 'Foo';
var f1 = new Foo();
Foo.prototype = {
name:'Foo_f2',
age:'22s'
};
var f2 = new Foo();
console.log(f1.name,f1.age, f2.name,f2.age);
//答案:Foo undefined Foo_f2 22s
---
var F = function (){}
Object.prototype.a = function(){
console.log('a执行')
}
Function.prototype.b = function(){
console.log('b执行')
}
var f1 = new F();
f1.a()
f1.b()
F.a()
F.b()
//答案 a执行 报错(f1原型链上没找到b方法)。 a执行 b执行
`