原型和原型链

209 阅读3分钟

一. 构造函数

任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要功能为初始化对象
对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。

1. 什么是构造函数?

在JS中用 new 关键字来实例化对象的函数,称为构造函数

2. 为什么需要 或者说会出现这个东西?解决什么问题?

在使用对象字面量创建一系列同一类型的对象时,这些对象可能具有一些相似的特征(属性)和行为(方法),此时会产生很多重复的代码,而使用构造函数就可以实现代码的复用。

3. 构造函数的执行过程

当一个函数创建好以后,我们并不知道它是不是构造函数,即使一般情况下构造函数首字母会大写。 只有当一个函数以 new 关键字来调用的时候,我们才能说它是一个构造函数。

1). 当以 new 关键字调用时,会创建一个新的内存空间,标记为该构造的实例。
2). this指向的就是新的内存空间,并执行构造函数内部代码,给实例增加属性
3). 返回this

4. 构造函数的返回值 默认为this

一般情况下不需要 手动添加 return 返回值。
当特殊情况发生,return一个基本类型变量时,返回值仍然是 this ; return 一个复杂数据类型时,返回值是该复杂数据类型。

二. 显式原型和隐式原型

  1. 每个函数function都有一个prototype,即显式原型
  2. 每个实例对象都有一个__proto__,可称为隐式原型
  3. 对象的隐式原型的值为其对应构造函数的显式原型的值
  4. 内存结构图

image.png 5. 总结: * 函数的prototype属性,在定义函数时自动添加的,默认值是一个空Object对象 * 对象的__proto__属性,在创建对象时自动添加的,默认值为构造函数的prototype属性值 * 程序员能直接操作显式原型,但不能直接操作隐式原型(es6之前)

3.原型链

  • 访问一个对象的属性时
  • 先在自身属性中查找,找到返回
  • 如果没有再沿着__proto__这条链向上查找,找到返回
  • 如果最终没找到,返回undefined

4.显式原型,隐式原型,构造函数之间关心图

image.png

image.png

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执行

`