JS深入学习笔记 - 第一章.构造函数原型与原型链

这篇具有很好参考价值的文章主要介绍了JS深入学习笔记 - 第一章.构造函数原型与原型链。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.构造函数和原型 

1.1 概述

在典型的 OOP语言中(如Java),都存在类的概念,类就是对象的模板,对象就是类的实例,但在ES6之前,JS并没有引入类的概念。

ES6之前,对象不是基于类创建的,而是一种称为构建函数的特殊函数来定义对象和它们的特征。

有三种创建对象的方式:

  1. 对象字面量(const obj = {name:'ab'})

  2. new Object()

  3. 自定义构造函数

//构造函数
function Star(uname,age){
​
    this.uname = uname;
    
    this.age = age
    
    this.sing = function(){
    
        console.log("我会唱歌")
    
    }
​
}
const ldh = new Star("刘德华",18)
const syz = new Star("孙燕姿",17)
console.log(ldh)
ldh.sing()
syz.sing()

 

1.2 构造函数

构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

 

在JS中使用构造函数是要注意以下两点:

  1. 构造函数用于创建某一类对象,其首字母要大写

  2. 构造函数要和new一起使用才有意义

     

new在执行时会做四件事情:

  1. 在内存中创建一个新的空对象

  2. 让this指向这个新的对象

  3. 执行构造函数里面的代码,给这个新对象添加属性和方法

  4. 返回这个新对象(所有构造函数里面不需要renturn)

 

1.3 实例成员和静态成员

实例成员:

构造函数内部通过this添加的成员 ,如下图的uname,age,sing就是实例成员

实例成员只能通过实例化的对象来访问

function Star(uname,age){
​
    this.uname = unamw;
​
    this.age = age
​
    this.sing = function(){
​
        console.log("我会唱歌")
​
    }
}
const ldh = new Star("刘德华",18)

静态成员:

静态成员在构造函数本身上添加的成员,如下图的sex就是静态成员

镜头成员只能通过构造函数来访问不能通过对象访问。

Star.sex = '男'
​
console.log('Star.sex')

 

1.4构造函数的问题

构造函数方法很好用,但存在浪费内存的问题

如:Star()构造函数中的sing()方法在每次实例化对象的时候都需要单独开辟一份内存空间,存在浪费空间的问题。

但是我们希望所有的对象使用同一个函数,这样就比较节省内存。

  //构造函数
    function Star(uname, age) {
      this.uname = uname;
​
      this.age = age;
​
      this.sing = function () {
        console.log("我会唱歌");
      };
    }
    
    const ldh = new Star("刘德华", 18);
    const syz = new Star("孙燕姿", 17);

 

思考:可是,为什么每次实例化都是单独开辟空间呢?

这个问题我查阅了很多的资料,总结一句话就是:在JS中,引用类型被创建的时候都会开辟一个新的空间。(其中的知识点比较多,详情请期待下一篇文章~)

 

1.5 构造函数原型prototype

构造函数通过原型分配的函数是所有对象所共享的。


JavaScript规定,每一个构造函数都有一个prototype 属性,指向另一个对象。

注意: 这个prototype就是一个对象,这个对象所有的属性和方法都会被构造函数所拥有

我们可以把那些不变的方法,直接定义在prototype 对象上,这样所有对象的实例就可以共享这些方法

function Star(uname,age){
​
    this.uname = unamw;
    
    this.age = age
}
Star.sing = function(){
    console.log("我会唱歌")
}
​
const syz = new Star('孙燕姿',20)
​
syz.sing()//我会唱歌

   
  1. 原型是什么? -------是一个对象,我们也称prototype为原型对象

  2. 原型的作用是什么? ------共享方法

 

1.6对象原型 __ proto __

对象都会有一个属性 __ prpto __ 指向构造函数的 prototype 原型对象,之所以对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有__ proto __ 原型的存在。

总结:
  • __ proto __ 对象原型和原型对象 prototype 是等价的

function Star(uname,age){
​
    this.uname = unamw;
    
    this.age = age
}
Star.sing = function(){
    console.log("我会唱歌")
}
​
const syz = new Star('孙燕姿',20)
console.log(syz.__ptoto === Star.prototype)//等价

 

  • __ proto __ 对象原型的意义就在于为对象的查找机制提供一个方向或者一条线路,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype。

     

1.7 constructor构造函数

对象原型(__ proto __)和构造函数原型对象(prototype)里面都有一个属性:constructor属性,constructor 我们称为构造函数,因为它指回构造函数本身

function Star(uname,age){
​
    this.uname = unamw;
    
    this.age = age
}
Star.prototype = {
    //这种情况下我们已经修改了原来prototype,给原型对象赋值的是一个对象,所有必须手动的把 constructor指回原来的构造函数
    constructor:Star,
    sing:function(){
        console.log("唱歌")
    }
    movie:function(){
        console.log("电影")
    }
}

 

 

1.8构造函数实例原型对象三者之间的关系

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

 

总结:构造函数和原型对象之间有互相可以表明对方身份的”信物“:prototype 和 constructor。

1.9 原型链

 

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

总结:

ldh对象实例的原型(__ proto __)可以找到它的对象原型——Star原型对象prototype;

通过Star原型对象prototype的原型(__ proto __),可以找到它的对象原型——Object原型对象 prototype;

通过Object原型对象 prototype的原型(__ proto __),可以找到它的对象原型——null(最顶层)。

因此形成的线路叫做原型链,为我们提供了某个属性或者函数的查找的线路

1.10 原型链查找规则

  1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性

  2. 如果没有就查找它的原型(也就是__ proto __ 指向的prototype原型对象

  3. 如果还没有就查找原型对象的原型Object的原型对象

  4. 以此类推一直找到最顶层(null)

1.11原型对象的this指向

function Star(uname,age){
​
    this.uname = unamw;
    
    this.age = age
}
​
let that;
 Star.prototype.sing = function(){
     that = this
    console.log("我会唱歌")
 }
const ldh = new Star("刘德华",18)
ldh.sing()
console.log(that === ldh)//true

 


构造函数(star)中 this 指向 创建的实例对象(ldh)。

sing函数只有调用之后才能确然this的指向,一般原则是:谁调用,this指向谁。

 

1.12 原型对象的应用

扩展内置对象

可以通过原型对象对原来的内置对象进行扩展自定义的方法。比如:给数组增加自定义求和的功能

Array.prototype.sum = function(){
    let sum = 0
    for(let i = 0;i < this.length; i++){
        sum += this[i]
    }
    return sum;
}
let arr1 = [1,4,5,6,8,9]
​
console.log(arr1.sum())//33
cosole.log(Array.prototype)//可以在arry中看到扩展的求和方法

 

2.继承

ES6 之前并没有给我们提供extends继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承


2.1call()

调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg, arg1, arg2... )

  • thisArg:当前调用函数this的指向对象

  • arg1 ,arg2: 传递的其他对象

const o = {
    name: 'zooey'
}
function fn(x,y){
    console.log("输出这个函数")
    console.log(this) // 此时 this 是 window
    console.log(x+y)
}
//普通调用的方式
fn()
​
//call调用方式: 使用对象调用, 此时的 this 是 o
fn.call(o) //此时 this 输出是 O
​
//call 做一些其他操作 比如:求出后两个参数的和
fn.call(o,5,2) //此时 this 输出是 O 

JS深入学习笔记 - 第一章.构造函数原型与原型链

2.2借用构造函数继承父类属性

核心原理:通过call 把父类的this 指向子类型的this ,这样就可以实现子类型继承夫类型的属性。

    function Father(uname, age) {
      this.uname = uname;
      this.age = age;
    }
​
    function Son(uname, age, score) {
      /**
      使用call调用Father 构造方法,
      并且把Father构造方法的this ,修改为Son的调用者
      传递参数uname,age,将参数也绑定给Father
      */
      Father.call(this, uname, age);
      this.score = score;
    }
​
    const son = new Son("lan", 26, 100);
    console.log(son);

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

注意点:

在 Son 构造函数中第一个参数是将 Son 的this传递给Father ,但是Son只有在实例化时才能知道this是谁。

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

初始化的参数通过Son传递给Father

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

 

2.3借用原型对象继承父类型方法

此处有一个思考:

在下图中,Array的原型对象中增加求和方法sum,在实例对arr1中就可以直接使用,但是在非实例化的形式中,如何实现方法的继承呢?

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

案例

function Father(uname, age) {
      this.uname = uname;
      this.age = age;
    }
​
    Father.prototype.getMoney = function () {
      console.log("挣钱");
    };
​
    function Son(uname, age, score) {
      /**
      使用call调用Father 构造方法,
      并且把Father构造方法的this ,修改为Son的调用者
      传递参数uname,age,将参数也绑定给Father
      */
      Father.call(this, uname, age);
      this.score = score;
    }
    Son.prototype.exam = function () {
      console.log("孩子考试");
    };
​
    const son = new Son("lan", 26, 100);
    console.log(son);
    son.exam();
    son.getMoney();

 

JS深入学习笔记 - 第一章.构造函数原型与原型链

 

| 可以看到上图中,son实例对象不能调用getMoney()方法

| 也不能将Father的prototype直接赋值给Son ,如下图

//直接赋值的操作
Son.prototype = Father.prototype;
Son.prototype.exam = function () {
      console.log("孩子考试");
 };
//此时对Son的prototype修改也会是 Father拥有 exam方法,因为现在是: Son的prototype 指向了Father 的 prototype,两个构造函数本质上是一个prototype.
console.log(Father);

 

注意: 此时对Son的prototype修改也会是 Father拥有 exam方法,因为现在是: Son的prototype 指向了Father 的 prototype,两个构造函数本质上是一个prototype.

正确的做法:

Son.prototype = new Father();
//记得将constructor指回 Son构造函数
Son.prototype.constructor = Son;
​
Son.prototype.exam = function () {
    console.log("孩子考试");
};
console.log(Father);

思考:记得将constructor指回 Son构造函数 的原因是什么呢?

尝试注释掉指回构造函数的代码,也可以正常输出,只不过没有constructor参数

JS深入学习笔记 - 第一章.构造函数原型与原型链

只是son实例可以归溯自己的构造函数是谁.文章来源地址https://www.toymoban.com/news/detail-709735.html

到了这里,关于JS深入学习笔记 - 第一章.构造函数原型与原型链的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《EDA技术实用教程(第六版)》学习笔记——第一章

    ASIC(Application-Specific Integrated Circuit):专用集成电路 SOC(System-on-Chip):片上系统 SOPC(System-on-Programmable-Chip):片上可编程系统 EDA(Electronic Design Automation):电子设计自动化 HDL(Hardware Description Language):硬件描述语言 FPGA(Field-Programmable Gate Array):现场可编程门阵列

    2024年01月17日
    浏览(48)
  • 人工智能( 第 3 版)第一章学习笔记

    第 1 章 人工智能概述 1.0 引言 本文对人工智能的观点:人工智能是由人(people)、想法(idea)、方法(method)、机器(machine)和结果(outcome)等对象组成的。人通过机器(计算机)将自己的想法以某种方法进行实现,最终实现的东西称为结果。 研究人工智能或实现人工智能系

    2024年01月25日
    浏览(50)
  • 云计算学习笔记--第一章(《云计算》刘鹏第三版)

    大数据时代 为什么全球数据量增长如此之快: 一方面是由于数据产生方式的改变。另一方面,人类的活动越来越依赖数据。一是人类的日常生活已经与数据密不可分。 何为大数据: 海量数据或巨量数据,其规模巨大到无法通过目前主流的计算机系统在合理时间内获取、存储、

    2023年04月09日
    浏览(45)
  • c++ 学习 之 构造函数的分类和调用类型 深入学习

    构造函数是在C++中用于创建和初始化对象的特殊函数。构造函数可以根据不同的特性和参数进行分类,以下是一些常见的构造函数分类和详细讲解它们的调用方式: 默认构造函数: 默认构造函数是一个特殊的构造函数,它没有参数,也可以没有具体的实现代码。如果没有显

    2024年02月10日
    浏览(40)
  • Rx.NET in Action 第一章学习笔记

    什么是反应式程序?它们有什么用?使用反应式扩展(Rx)编程,会如何改变你编写代码的方式?在开始使用 Rx 之前应该做些什么?为什么 Rx 比传统的事件驱动编程更好? 这些都是我们将在前三章开始讨论的问题。 你将了解什么是反应式系统及反应式程序,以及为什么要关

    2024年02月13日
    浏览(51)
  • ROS2 Navigation 进阶教程学习笔记 第一章

    Nav2提供了新的拱你和工具,使创建机器人应用程序变得更容易 在本单元中,将学习 1. 通过simple Commander API进行基本Nav2操作 2. 通过followwaypoints使用waypoint follower和task executor插件 3. 禁区和限速区简介 然后您将基于Nav2创建一个基本的自主机器人demo。您将经常在一个仿真仓库中

    2024年02月08日
    浏览(48)
  • 《Pytorch深度学习和图神经网络(卷 2)》学习笔记——第一章

    PyTorch深度学习和图神经网络(卷2)——开发应用一书配套代码: https://github.com/aianaconda/pytorch-GNN-2nd- 百度网盘链接:https://pan.baidu.com/s/1dnq5IbFjjdekAR54HLb9Pg 提取码:k7vi 压缩包密码:dszn 2012年起,在ILSVRC竞赛中获得冠军的模型如下 2012年:AlexNet 2013年:OverFeat 2014年:GoogLeNet、

    2024年02月16日
    浏览(46)
  • 《MetaGPT智能体开发入门》学习笔记 第一章第二章

    使用从 - 通过github仓库获取MetaGPT 代码拉下来后在config文件夹中配置chatGPT key 使用的python环境为3.9.2 metaGPT代码下载后在metagpt文件夹中找statup.py文件,运行以下命令,我是没有成功可能是chatgpt没钱 智能体 = LLM+观察+思考+行动+记忆 多智能体 = 智能体+环境+SOP+评审+路由+订阅+经

    2024年01月17日
    浏览(59)
  • 《EDA技术实用教程(第六版(黄继业, 潘松))》学习笔记——第一章

    ASIC(Application-Specific Integrated Circuit):专用集成电路 SOC(System-on-Chip):片上系统 SOPC(System-on-Programmable-Chip):片上可编程系统 EDA(Electronic Design Automation):电子设计自动化 HDL(Hardware Description Language):硬件描述语言 FPGA(Field-Programmable Gate Array):现场可编程门阵列

    2024年01月22日
    浏览(46)
  • JavaScript Es6_2笔记 (深入对象 + 内置构造函数 + 包装类型)+包含实例方法

    了解面向对象编程的基础概念及构造函数的作用,体会 JavaScript 一切皆对象的语言特征,掌握常见的对象属性和方法的使用。 了解面向对象编程中的一般概念 能够基于构造函数创建对象 理解 JavaScript 中一切皆对象的语言特征 理解引用对象类型值存储的的

    2024年02月12日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包