编程技术文章分享与教程

网站首页 > 技术文章 正文

日常复习之一文搞懂JavaScript原型链

hmc789 2024-11-10 10:34:14 技术文章 2 ℃

大家一说到原型链知识的都会有这张图。

1) 原型对象与原型属性

  • prototype:原型对象,函数在声明的时候自动创建的一块存储区域,用于存储公共的共享属性和方法
  • __ __proto__: 原型属性,每一个实例对象在创建的时候都会有一个原型属性__proto__,指向构造函数的prototype

所以可以看出构造函数的prototype和实例对象的__proto__是true指向同一个地方。

什么是构造函数呢?就是new的函数并且首字母是要大写的函数就是构造函数。

平时定义的函数有以下几种方式

function aa(name,age){console.log(name,age)}
aa(“张三”,19)

var bb = function (name,age){console.log(name,age)}
bb("李四",22)

const arrowFn = (name, age) => {
  console.log(`我是${name}, 我今年${age}岁`)
}
arrowFn('王五', 10)

其实这几种的本质都是一样的(只考虑函数的声明),都可以使用new Function来声明,是的没错Function也是一个构造函数。上面的写法等同于下面的写法

const aa = new Function(name,age){console.log(name,age)}
aa(“张三”,19)
const bb = new Function(name,age){console.log(name,age)}
bb("李四",22)
const arrowFn = new Function(name,age){ console.log(`我是${name}, 我今年${age}岁`))}
arrowFn('王五', 10)

所以这里的aa,bb,arrowFn其实就是new Function(){}构造函数的实例,举一个例子

对象

咱们平常开发中,创建一个对象,通常会用以下几种方法。

  • 构造函数创建对象,他创建出来的对象都是此Function构造函数的实例,所以这里不讨论它
  • 字面量创建对象
  • new Object创建对象
  • Object.create创建对象,创建出来的是一个空原型的对象,这里不讨论它
//1.字面量创建
var obj1 = {
    //属性
    "name":"如花",
    "age":18,
    "sex":"男",
    //方法
    "skill":function(){
        console.log("抠脚");
    }
}
console.log(obj1);
//问题:代码冗余,适合创建单个对象

//2.实例实例(单例)
var obj2 = new Object();  //创建一个空对象
//添加属性
obj2.name = "连海龙";
obj2.sex = "男",
    //添加方法
    obj2.skill = function(){
    console.log("玩游戏");
}
console.log(obj1);
//问题:代码冗余,适合创建单个对象

咱们来看看字面量创建对象和new Object创建对象两种方式,
其实字面量创建对象的本质就是new Object创建对象

//3.工厂模式创建(普通函数封装)
function createObj(name,age,height){
    //创建对象
    var obj = new Object();
    //添加属性
    obj.name = name;
    obj.age = age;
    obj.height = height;
    //添加方法
    obj.skill = function(){
        console.log("有钱");
    }
    //返回创建好的对象
    return obj;
}
//实例化对象
var obj1 = createObj("吴亦凡",65,179);
console.log(obj1);
var obj2 = createObj("蔡徐坤",30,182);
console.log(obj2);

var obj3 = createObj("旺财",2,30);
console.log(obj3);

//问题:解决代码冗余的问题,识别不明,无法判断对象的类型
console.log(typeof obj2,typeof obj3); //object object
console.log(obj3 instanceof Object); //true 判断实例对象是否由 后面的这个对象创建

//4.声明构造函数
function Student(name, age, sex) {
    //1.隐式的创建了一个空对象,让this指向这个空对象
    //this = new Object();

    //2.执行构造函数中代码(添加属性和方法)
    //添加属性
    this.name = name;
    this.age = age;
    this.sex = sex;
    //添加方法
    this.study = function () {
        console.log("good good study,day day up!!!,好好学习,天天自闭");
    }

    //4.隐式的返回创建好的对象
    //return this
}

var s2 = new Student("曾庆文",18,"女");
console.log(s2); // {name: "曾庆文", age: 18, sex: "女", study: ?}
console.log(s2 instanceof Student); //true
//.实例化对象
var s1 = new Student("李华",10,"男"); 
var s2 = new Student("曾庆文",18,"女");

//问题:解决了识别不明的问题,浪费内存
console.log(s1.study == s2.study);//false  比较的是地址

// new 操作符的作用
1.隐式的创建了一个空对象,让this指向这个空对象
2.执行构造函数中代码(添加属性和方法)
3.让创建的实例对象的__proto__指向构造函数的prototype
4.隐式的返回创建好的对象


原型对象,函数在声明的时候自动创建的一块存储区域,用于存储公共的共享属性和方法

Function和Object

上面咱们常说

  • 函数是Function构造函数的实例
  • 对象是Object构造函数的实例

那Function构造函数和Object构造函数他们两个又是谁的实例呢?

  • function Object()其实也是个函数,所以他是Function构造函数的实例
  • function Function()其实也是个函数,所以他也是Function构造函数的实例,没错,他是他自己本身的实例

咱们可以试验一下就知道了

console.log(Function.prototype === Object.__proto__) // true
console.log(Function.prototype === Function.__proto__) // true

constructor

constructor和prototype是成对的,你指向我,我指向你。举个例子,如果你是我老婆,那我肯定是你的老公。

function fn() {}

console.log(fn.prototype) // {constructor: fn}
console.log(fn.prototype.constructor === fn) // true

原型链

Person.prototype 和 Function.prototype

讨论原型链之前,咱们先来聊聊这两个东西

  • Person.prototype,它是构造函数Person的原型对象
  • Function.prototype,他是构造函数Function的原型对象

都说了原型对象,原型对象,可以知道其实这两个本质都是对象

那既然是对象,本质肯定都是通过new Object()来创建的。既然是通过new Object()创建的,那就说明Person.prototype 和 Function.prototype都是构造函数Object的实例。也就说明了Person.prototype 和 Function.prototype他们两的__proto__都指向Object.prototype

咱们可以验证一下

function Person(){}

console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true
复制代码

什么是原型链?

什么是原型链呢?其实俗话说就是:__proto__的路径就叫原型链

原型链终点

上面咱们看到,三条原型链结尾都是Object.prototype,那是不是说明了Object.prototype就是原型链的终点呢?其实不是的,Object.prototype其实也有__proto__,指向null,那才是原型链的终点

至此,整个原型示意图就画完啦!!!

原型继承

说到原型,就不得不说补充一下原型继承这个知识点了,原型继承就是,实例可以使用构造函数上的prototype中的方法

function Person(name) { // 构造函数
  this.name = name
}
Person.prototype.sayName = function() { // 往原型对象添加方法
  console.log(this.name)
}


const person = new Person('林三心') // 实例
// 使用构造函数的prototype中的方法
person.sayName() // 林三心
复制代码

instanceof

使用方法

A instanceof B
复制代码

作用:判断B的prototype是否在A的原型链上

例子

function Person(name) { // 构造函数
  this.name = name
}

const person = new Person('林三心') // 实例

console.log(Person instanceof Function) // true
console.log(Person instanceof Object) // true
console.log(person instanceof Person) // true
console.log(person instanceof Object) // true

最后:记住一句话, 万物皆有__proto__,只有function才会有prototype

参考文章 链接:https://juejin.cn/post/7007416743215759373

标签列表
最新留言