js原型和原型链你只要看这一篇

2023-11-14

一、原型概述

    任何对象都有一个原型对象,这个原型对象由对象的内置属性_proto_指向它的构造函数的prototyoe指向的对象,即任何对象都是由一个构造函数创建的,被创建的对象都可以获得构造函数的prototype属性,注意:对象是没有prototype属性,只有方法才有prototype属性。

    任何对象都有一个constructor属性,指向创建此对象的构造函数,比如说{}对象,它的构造函数是function Object(){}。

 

	function Person() {
	}
	var p = new Person();
	//方法才有prototype,普通对象无prototype
	console.log(Person.prototype); // Object{} 
	console.log(p.prototype); // undifined
	
	//任何对象都是有构造函数constructor,由构造函数创建的对象也可以获得构造函数的引用
	//此处只是打印下列对象的构造函数是什么。
	console.log(p.constructor); //function Person(){}  
	console.log(Person.constructor); //function Function(){} 
	console.log({}.constructor); // function Object(){}
	console.log(Object.constructor); // function Function() {}
	console.log([].constructor);  //function Array(){} 

    那什么是构造函数呢?

    用function声明的都是函数,而如果直接调用的话,那么Person()就是一个普通函数,只有用函数new产生对象时,这个函数才是new出来对象的构造函数

二、创建对象的过程

    2.1 、声明方法的过程

    首先,当我们声明一个function关键字的方法时,会为这个方法添加一个prototype属性,指向默认的原型对象,并且此prototype的constructor属性就是此方法。此二个属性会在创建对象时被对象的属性引用。

	function Hello() {
	}
	console.log(Hello.prototype); // Object {} -- > 内部的constructor 指向Hello方法
	console.log(Hello.prototype.constructor); // function Hello(){}

  2.2、创建一个对象,从构造函数继承了什么属性?

    console.log(h.constructor); // function Hello(){}
    console.log(Object.getPrototypeOf(h)==Hello.prototype); // true  备注:getPrototypeOf是获取_proto_

  我们惊喜的发现,new出来的对象,它的constructor指向了方法对象,它的_proto_和prototype相等。

  即new一个对象,它的_proto_属性指向了方法的prototype属性,并且constructor指向了prototype的constructor属性。

  由构造函数创建一个对象,此对象多了一个_proto_属性指向构造函数的prototype,一个constructor属性指向构造函数的prototype的constructor属性。

  2.3 、创建一个对象的过程

	function Hehe(name) {
		this.name = name;
	}
	var h = new Hehe("笑你妹");
	//伪代码:
	function newObj(name){
		 var obj = {};
		 obj.__proto__ = Hehe.prototype; 
		 obj.constructor = Hehe.prototype.constructor;
		 var result = Hehe.call(obj, name);
		 return typeof result==='object'&& result!=null ? result : obj;  //当无返回对象或默认时返回obj。
	}
	var hh = newObj("笑你妹");
	console.log(hh);
	console.log(h);
	//虽然hh!=h,但是可以看到这个hh就和h的结构一样了。

    过程:先创建一个空对象,设置一个_proto_指向方法的原型,设置constructor,用新对象做this指向方法,返回新对象。

2.4、总结

    从上面说明的过程中,我们发现只要是对象就是有构造函数来创建的,并且内部二个属性是从构造函数的prototype衍生的一个指向,而构造函数的prototype也是一个对象,那么它应该肯定也有一个构造函数,首先它是一个Object {} 对象,那么它的构造函数肯定是Object,所以就会有一个指针_proto_指向Object.prototype。最后Object.prototype因为没有_proto_,指向null,这样就构成了一个原型链。

    三、原型链分析

    什么是原型链?

    原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。

    如何分析原型链?

    因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,等于null。

    3.1、最简单的原型链分析

    function Person(name){
            this.name = name;
     }
     var p = new Person();
     //p ---> Person.prototype --->Object.prototype---->null

     上面原型链的分析:p的构造函数是Person创建的,那么Person.prototype就是继承的第一个原型,而Person.prototype没有自定义设置,默认就是一个Object对象,即是Object构造函数创建的,那么就是继承了Object.prototype,而Object.prototype再往上就没有_proto_指向了,等于null

    属性搜索原则:
     1.当访问一个对象的成员的时候,会现在自身找有没有,如果找到直接使用。
     2.如果没有找到,则去原型链指向的对象的构造函数的prototype中找,找到直接使用,没找到就返回undifined或报错。

     3.2、原型继承

//原型继承的基本案例
function Person(name, age) {
	this.name = name;
	this.age = age;
}
//1.直接替换原型对象 
var parent = {
	sayHello : function() {
		console.log("方式1:替换原型对象");
	}
}
Person.prototype = parent;
var p = new Person("张三", 50);
p.sayHello();
//2.混入式原型继承
console.log(".............混入式原型继承..............");
function Student(name, age) {
	this.name = name;
	this.age = age;
}
var parent2 = {
	sayHello : function() {
		console.log("方式2:原型继承之混入式加载成员");
	}
}
for ( var k in parent2) {
	Student.prototype[k] = parent2[k];
}
var p = new Student("张三", 50);
p.sayHello();

    3.3 原型链案例

// 查询原型链上的对象的方法
function findProtoType(obj) {
  var arr = [];
  while (obj != null) {
    obj = Object.getPrototypeOf(obj);
    arr.push(obj);
  }
  return arr;
};

function Root() {}

function Child() {}

Child.prototype = new Root();
Child.prototype.constructor = Child; // 这个步骤是为了让原型对象打印显示成自身(继承prototype同时也继承了constructor,因此替换成自身)

function Item() {}

Item.prototype = new Child();
Item.prototype.constructor = Item;

var result = findProtoType(new Item());
console.log(result);
//  [ Item { constructor: [Function: Item] },Child { constructor: [Function: Child] }, Root {}, {}, null ]

谢谢观看!

end!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js原型和原型链你只要看这一篇 的相关文章

  • Vue-cli的安装与配置

    Node的下载与安装 工欲善其事必先利其器 在搭建vue的开发环境之前 一定一定要先下载node js vue的运行是要依赖于node的npm的管理工具来实现 1 首先我们进入到node的官网 https nodejs org zh cn
  • CSS之背景样式及边框样式

    1 背景样式 常用属性 background color 背景颜色 background image 背景图片 background repeat 背景图片的平铺方式 background position 背景图片的位置 backgrou
  • web前端入门到实战:CSS遮罩效果、阴影效果、毛玻璃效果

    一般遮罩 background 000 在body标签的最后加上div标签作为遮罩 如下 div class mask div css样式 mask position fixed top 0 left 0 bottom 0 right 0
  • <form>表单

    1 form表单
  • 前端性能优化

    页面的性能指标 DCL DOMContentLoaded DOM解析完毕 FP First Paint 表示渲染出第一个像素点 FP一般在HTML解析完成或者解析一部分时候触发 FCP First Contentful Paint 表示渲染
  • 打造高大上的Canvas粒子动画

    首先来看下我们准备要做的粒子动画效果是怎么样的 是这样 或者是这样 甚至是这样 很酷炫 那如何去实现类似上面的粒子动画甚至根据自己的喜好去做更多其他轨迹的动画呢 请看下面详细的讲解 技术选择 因为粒子数量很多 而且涉及到图像像素处理 所以这
  • Layui富文本编辑器图片上传接口(.NET C#)

    本来想偷懒找个现成的接口 搜了一下发现没有现成的 那我在这写一个并分享给大家吧 demo打包好了在我的csdn下载中心 http download csdn net download xianglikai1 9970000 下面也有代码和结
  • css3颜色渐变:css3如何实现背景颜色渐变?

    为了开发网页的美观 css3背景颜色渐变是经常会用到的 那么 css3背景颜色渐变如何设置呢 本篇文章我们就来介绍关于css颜色渐变背景的设置方法 我们要知道的是css3渐变有两种类型 css3线性渐变和css3径向渐变 下面我们就来看一下
  • ajax请求不能下载文件

    最近在做文件下载 后台写了个控制层 直接走进去应该就可以下载文件 各种文件图片 excel等 但是起初老是下载失败 并且弹出下面的乱码 前台请求代码 fileexcel unbind click bind click function al
  • Html页面内引入抽取出来的Html,js,css示例

    在写纯Html网站的时候 每个页面的头部菜单 js css和底部说明都是同样的 有的时候你要改 就要一个一个的去改 通过下面方法将这些相同的抽取出来 方便后期维护 希望能帮到你 在applyBusiness html页面引入公共页头head
  • vue 循环遍历 搜寻资料

    写vue 循环遍历的 大全例子解释 转载连接 https www cnblogs com xulei1992 p 6015416 html https www jqhtml com 49765 html https blog csdn ne
  • React 中ref的几种用法

    React 中ref的几种用法 1 字符串 通过 this refs a 来引用真实dom的节点 dom 节点上使用
  • ES6语法知识点

    目录 let const 常用 暂时性死区 const 建议 箭头函数 常用 建议 iterator迭代器 解构赋值 常用 建议 剩余 扩展运算符 常用 扩展运算符 剩余运算符 在对象中使用扩展运算符 建议 对象属性 方法简写 常用 对象属
  • uniapp的那些坑

    1 selectedColor不起作用 1 查看位置是否写对 与lis同级 2 是否为16进制 selectedColor写的rgb不支持 3 是否被其他样式覆盖 其他地方也设置过selectedColor 可以全局搜索一下 2 pages
  • 关于2018网易游戏web前端实习生面试经历

    去年报名的网易前端面试 没想到过了3个月居然收到了面试的通知 心里也是激动 花了一天时间面试 自己总结一下面试过的问题 问题可能不全 但是这些是我所能记起来的问题 一面 1 css高度坍塌 两个盒子 一个下边据20px 一个上边据50px
  • 微信小程序开发实战第五讲之授权登录

    上一节 我们实现了简单的通过用户名和密码调用接口进行登录的实战 但是在小程序中 有个特殊的情况 就是很少有厂商去开发一个注册功能或者是通过用户名 密码来登录的逻辑 为什么 因为APP 小程序为了用户体验 是尽量多的避免用户多次输入交互 所以
  • CSS 学习笔记(基础)

    用来控制网页表现的语言 CSS Cascading Style Sheet 层叠样式表 然后我们继续看看 W3C 标准 结构 HTML 表现 CSS 行为 JavaScript CSS导入方式 选择器 属性 由于网页的框架结构是由HTML实
  • laravel路由

    路由 在laravel中 定义路由的地方在routes web php文件中 在使用laravel前必须先定义路由 然后才能在浏览器中访问 routes文件夹中还有一个api php 用于定义api路径 最简单的路由 Route get f
  • react(craco)移动端使用postcss-px-to-viewport自适应布局

    Craco 使用postcss px to viewport devDependencies craco craco 6 4 3 xianzhengquan postcss px 2 vw 0 0 1 postcss 8 3 0 peerD
  • <a>标签的超链接前面会自动加上当前(网站)地址

    当前 网站 地址是 fyh com 在代码里写 a 标签时 会自动在链接前添加 fyh com 例如写如下代码 a href www baidu com baidu a 在浏览器中点击链接会跳转至 fyh com www baidu com

随机推荐

  • Unity 初识:坐标系与向量

    世界坐标系 场景中的绝对坐标系 场景上所有物体都是以该坐标系的原点来确定各自位置的 世界坐标即物体在世界坐标系中的位置 局部坐标系 以物体的世界坐标为原点 角度为朝向 大小为单位 所产生一个新的坐标系 该坐标系中 物体的位置 旋转 大小都会
  • 免费国外视频素材网站

    这里自己收藏几个可以免费下载国外视频的网站 希望大家喜欢 可以的话给个关注哟 Pexels Videos https videos pexels com Pexels 是一个著名的免费图片平台 每天都会有大量的设计师和博客写手来这里为他们的
  • 前端接入萤石云

    萤石云有两个方法使用 npm引入 非npm引入 两个方法中的js内容不同 所以容器初始化方法也不同 详情可到github查看 https github com Hikvision Ezviz npm引入 步骤一 首先通过npn下载 npm
  • 对字符串按照一定的长度来分行或者添加其他数据

    核心代码 对字符串按照一定的长度来分行或者添加其他数据 param str 原始字符串 param int length 插入的间隔长度 param string append 需要插入的字符串 return string 返回字符串 fu
  • 【程序员面试金典】实现一个函数,检查二叉树是否平衡,

    题目描述 实现一个函数 检查二叉树是否平衡 平衡的定义如下 对于树中的任意一个结点 其两颗子树的高度差不超过1 给定指向树根结点的指针TreeNode root 请返回一个bool 代表这棵树是否平衡 题目分析 lt 方法1 gt 平衡二叉
  • [附代码]多输入AD模数转换,数据接受模块 Verilog 实现 (授人与渔)

    要素察觉 本文基于 AD7888 八输入通道 模数转换芯片 对转换后的数据在 FPGA 中进行接收 所使用的 HDL 为 Verilog 所有实现步骤依据 AD7888 DataSheet 中给出的相关数据和时序图 对原理和相应 Veril
  • mysql中的锁

    锁分类 MySQL中的锁 按照锁的粒度分 分为以下三类 1 全局锁 锁定数据库中的所有表 2 表级锁 每次操作锁住整张表 3 行级锁 每次操作锁住对应的行数据 全局锁 全局锁就是对整个数据库实例加锁 加锁后整个实例就处于只读状态 后续的DM
  • 网易笔试题

    网易笔试不难 但是给了我一个教训 所以记下来以留念 时间 11月3日8 00 后来改到10 00 地点 西安交通大学教2南315教室 赶到考场时 离考试开始时间只差2分钟了 找了个座位坐下后没有任何的等待笔试就开始了 网易的笔试题目很有趣
  • CVE-2023-21839 【vulhub weblogic 漏洞复现】

    漏洞概述 由于Weblogic IIOP T3协议存在缺陷 当IIOP T3协议开启时 允许未经身份验证的攻击者通过IIOP T3协议网络访问攻击存在安全风险的WebLogic Server 漏洞利用成功WebLogic Server可能被
  • ffmpeg命令大全

    ffmpeg命令大全 FFMPEG 目录及作用 FFMPEG基本概念 FFMPEG 命令 基本信息查询命令 主要参数 视频参数 音频参数 录制 录屏 分解与复用 滤镜 简单滤镜 复杂滤镜 直播相关 前言 FFMPEG是特别强大的专门用于处理
  • c/c++获取文夹下所有图片文件路径

    在做项目的时候 我们有时候会遇到给定一个文件夹目录 获取该目录下某种类型的文件的路径 也就是遍历一个目录下的所有文件 经过查询 发现可以通过 代码实例 获取某一目录下所有的 jpg文件路径 include
  • Java知识点汇总第二篇(红色为重点内容,黄色为应用较多的,蓝色为了解的

    一 1 标识符 定义 用来表示变量名 类名 方法名 数组名和文件名的有效字符序列 以字母 下划线 美元符号等开始 后面可以跟字母 下划线 美元符号 数字等字符 注 不能以数字开始 大小写敏感 不能与关键字相同 2 关键字 定义 Java中被
  • 计算机网络-6-应用层

    Lecture06 应用层 本节PPT包含5 7三层 The Session Layer 会话层 The Presentation Layer 展示层 The Application Layer 应用层 1 第五层 The Session
  • 性能测试常见指标有哪些

    性能测试的常见指标包括 1 响应时间 Response Time 用户发送请求到系统返回结果所花费的时间 2 吞吐量 Throughput 单位时间内系统处理的请求数量 通常以每秒请求数 SPS或TPS 表示 3 并发用户数 Concurr
  • libev学习系列之三:libev编译安装

    libev学习系列之三 libev编译安装 版本说明 版本 作者 日期 备注 0 1 ZY 2019 5 31 初稿 目录 文章目录 libev学习系列之三 libev编译安装 版本说明 目录 源码结构 正常编译 交叉编译 源码结构 4 2
  • 龙书虎书鲸书啃不动?试试豆瓣评分9.5的猴书

    相传 编译原理界有三大圣书 龙书是为Compilers Principles Techniques and Tools 虎书是为Modern Compiler Implementation in C 鲸书是为Advanced Compile
  • python自动化办公(三十一)TKinter 先登录授权窗口,授权成功后进入master主窗口

    一 主简介 先登录授权窗口 比如验证账号密码信息等等 授权成功后进入master主窗口 验证成功后 进入主页面 Tkinter实现登录成功后进入主界面 月半的博客 CSDN博客 tkinter登录成功跳转主窗体
  • 安装Pycharm工具 -- ubuntu18.04

    在Ubuntu18 04下 pycharm工具的安装及其快捷方式的创建 下载pycharm安装包 tar gz包 网址 https www jetbrains com pycharm tar gz 安装包解压缩 此处没有指定解压到哪个路径
  • 最经典的黑客技术入门知识

    最经典的黑客技术入门知识 整理 Ackarlix 第一节 什么是黑客 以我的理解 黑客 大体上应该分为 正 邪 两类 正派黑客依靠自己掌握的知识帮助系统管理员找出系统中的漏洞并加以完善 而邪派黑客则是通过各种黑客技能对系统进行攻击 入侵或者
  • js原型和原型链你只要看这一篇

    一 原型概述 任何对象都有一个原型对象 这个原型对象由对象的内置属性 proto 指向它的构造函数的prototyoe指向的对象 即任何对象都是由一个构造函数创建的 被创建的对象都可以获得构造函数的prototype属性 注意 对象是没有p