查漏补缺 - 构造函数,原型,this,原型链,继承

目录

  • 1,构造函数
  • 2,原型
  • 3,this
  • 4,原型链
    • 1,特点
    • 2,Object.prototype.toString()
    • 3,instanceof 运算符
    • 4,Object.getPrototypeOf()
    • 5,创建空原型对象
    • 6,面试题
  • 5,继承
    • 封装继承

1,构造函数

1,作用:创建对象。

通过普通函数返回对象:

function createPerson(firstName, lastName) {var obj = {}obj.firstName = firstNameobj.lastName = lastNameobj.fullName = firstName + lastNameobj.myName = function () {console.log(obj.fullName)}return obj
}const person = createPerson('张', '三')

通过构造函数创建对象

function Person(firstName, lastName) {this.firstName = firstNamethis.lastName = lastNamethis.fullName = firstName + lastNamethis.myName = function () {console.log(this.fullName)}
}const person = new Person('张', '三') // 规定语法

2,js 中所有的对象,都是通过构造函数创建的。

Object() 构造函数,所以 typeof Object === 'function'

var obj = {age: 18
}// 上面是语法糖var obj = new Object()
obj.age = 18

Function()构造函数

每个 js 函数实际上都是一个 Function 对象,通过 Function 构造函数创建时(可以不加 new 关键字)。

const add= new Function("a", "b", "return a + b");
add(2, 6);

2,原型

当构造函数中定义方法时,因为每个构造出的实例都是独立的,所以每次也会创建一个新的方法。

function Foo(a, b) {this.a = athis.b = bthis.sayHi = function () {console.log(this.a + this.b)}
}const foo1 = new Foo(1, 2)
const foo2 = new Foo(1, 2)console.log(foo1.sayHi === foo2.sayHi) // false

这会造成内存空间的浪费,所以出现了原型来解决这个问题。

当访问实例成员时,先找自身,如果不存在,会自动从隐式原型中寻找。

原型也是一个对象,一般会将公共的方法放到原型上。

function Foo(a, b) {this.a = athis.b = b
}Foo.prototype.sayHi = function () {console.log(this.a + this.b)
}const foo1 = new Foo(1, 2)
const foo2 = new Foo(1, 2)console.log(foo1.sayHi === foo2.sayHi) // true

在这里插入图片描述

3,this

1,在函数中使用 this,它的指向完全取决于函数是如何调用的。具体参考

例子,为所有对象添加方法 print,并打印对象的键值对。

Object.prototype.print = function () {for (var key in this) {// 过滤掉 printif (this.hasOwnProperty(key)) {console.log(key, this[key])}}
}var obj = {a: 1,b: 2
}console.log(obj.print())

2,hasOwnProperty

表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。

3,in 运算符

判断属性名是否在对象自身及其原型链上。

4,原型链

在这里插入图片描述

1,特点

  1. Object.prototype 上添加属性,会影响到所有对象,包括函数和数组。

  2. Function.prototype 上添加属性,会有影响到所有函数,所以可以判断一个变量是不是函数。

Function.prototype.isFun = truevar obj = {}
function fun() {}console.log(obj.isFun) // undefined
console.log(fun.isFun) // true

2,Object.prototype.toString()

MDN - Object.prototype.toString()

会把对象转为字符串格式 [object Object],但这种格式并不是每个对象想要的。

所以数组重写了 toString 方法

Array.prototype.toString === Object.prototype.toString // false

如何让数组的 toString 方法使用 Object.prototype.toString

const arr = [1,2,3]
Object.prototype.toString.call(arr)

所以判断一个变量是不是数组的方法:

const arr = [];
console.log(Object.prototype.toString.call(arr)); // [object Array]

如果自己的构造函数希望改变 toString,如何改变?

function User() {}
const user = new User();User.prototype.toString = function () {return "xxx";
};console.log(user.toString()); // xxx

3,instanceof 运算符

MDN - instanceof 运算符

用于检测构造函数的 prototype,是否出现在某个实例对象的原型链上。

function User() {}var user = new User()console.log(user instanceof User) // true
console.log(user instanceof Object) // true

o in C 更多的用来判断对象 o 是不是构造函数 C 的创建的实例。

所以,可以这样理解:

obj instanceof Array // obj 是不是数组
obj instanceof Object // obj 是不是对象
obj instanceof Function // obj 是不是函数

4,Object.getPrototypeOf()

Object.getPrototypeOf()

因为不推荐使用 __proto__,所以有了新的方法来操作隐式原型:Object.getPrototypeOf()Object.setPrototypeOf()

const arr = [];
console.log(Object.getPrototypeOf(arr) === arr.__proto__); // true

5,创建空原型对象

方法1,

const obj = {}
obj.__proto__ = null // 不推荐 直接操作 __proto__Object.setPrototypeOf(obj, null) // 可以使用

方式2,

const obj = Object.create(null)

6,面试题

下面的面试题,都可以用上面的原型链图快速解释。

// 下面的代码输出什么?(京东)
Function.prototype.a = 1;
Object.prototype.b = 2;function A() {}var a = new A();console.log(a.a, a.b); // undefined 2
console.log(A.a, A.b); // 1 2
// 下面的代码输出什么?(字节)
console.log({} instanceof Object); // true
console.log({}.toString instanceof Function); // true
console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
// 下面的代码输出什么?
function User() {}
User.prototype.sayHello = function () {};var u1 = new User();
var u2 = new User();console.log(u1.sayHello === u2.sayHello); // true
console.log(User.prototype === Function.prototype); // false
console.log(User.__proto__ === Function.prototype); // true
console.log(User.__proto__ === Function.__proto__); // true
console.log(u1.__proto__ === u2.__proto__); // true
console.log(u1.__proto__ === User.__proto__); // false
console.log(Function.__proto__ === Object.__proto__); // true
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); // false
console.log(Function.prototype.__proto__ === Object.prototype); // true

5,继承

假设有一个会员系统

  • 免费用户
    • 属性:用户名,密码
    • 方法:播放免费视频
  • vip 用户
    • 属性:还有会员过期时间
    • 方法:还有播放vip视频
function User(name, pwd) {this.name = namethis.pwd = pwd
}User.prototype.playFreeVideo = function() {console.log('免费视频');
}function VipUser(name, pwd, expires) {this.name = namethis.pwd = pwdthis.expires = expires
}VipUser.prototype.playFreeVideo = function() {console.log('免费视频');
}VipUser.prototype.playVipVideo = function() {console.log('vip视频');
}

可以看到有冗余的代码。改造下

1,处理构造函数内部的重复。

function VipUser(name, pwd, expires) {User.call(this, name, pwd)this.expires = expires
}

2,处理原型上的重复

需要一个图来表现关系

// VipUser.prototype.__proto__ = User.prototype
Object.setPrototypeOf(VipUser.prototype, User.prototype)

继承就是上面这种关系。

  • 子类的实例,应该自动拥有父类的所有成员。
  • 子类最多只有一个父类
  • 间接父类的成员,会传递给子类

封装继承

function inherit(Child, Parent) {Object.setPrototypeOf(Child.prototype, Parent.Parent)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令:v-html、v…

【无需公网IP】在树莓派上搭建Web站点

目录 1.概述 2.使用 Raspberry Pi Imager 安装 Raspberry Pi OS 3.设置 Apache Web 服务器 3.1测试 web 站点 3.2安装静态样例站点 3.3将web站点发布到公网 3.4安装 Cpolar 3.5cpolar进行token认证 3.6生成cpolar随机域名网址 3.7生成cpolar二级子域名 3.8将参数保存…

基于Android的课程教学互动系统 微信小程序uniapp

教学互动是学校针对学生必不可少的一个部分。在学校发展的整个过程中,教学互动担负着最重要的角色。为满足如今日益复杂的管理需求,各类教学互动程序也在不断改进。本课题所设计的springboot基于Android的教学互动系统,使用SpringBoot框架&am…

接口幂等性设计的最佳实现

一、什么是幂等 二、为什么需要幂等 三、接口超时了,到底如何处理? 四、如何设计幂等 全局的唯一性ID 幂等设计的基本流程 五、实现幂等的8种方案 selectinsert主键/唯一索引冲突 直接insert 主键/唯一索引冲突 状态机幂等 抽取防重表 token令牌 悲观锁…

【Go 基础篇】Go语言结构体基本使用

在Go语言中,结构体是一种重要的数据类型,用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型,类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比&#…

系统学习Linux-ELK日志收集系统

ELK日志收集系统集群实验 实验环境 角色主机名IP接口httpd192.168.31.50ens33node1192.168.31.51ens33noed2192.168.31.53ens33 环境配置 设置各个主机的ip地址为拓扑中的静态ip,并修改主机名 #httpd [rootlocalhost ~]# hostnamectl set-hostname httpd [root…

Jupyter installation Tutorial

文章目录 1. 面向的系统2. 什么是Jupyter?3. 安装Python环境4. 安装Jupyter notebook5. Jupyter的启动和配置6. Jupyter的使用技巧7. conclusion参考文献 1. 面向的系统 Windows安装 2. 什么是Jupyter? Jupyter Notebook是一个开源的Web应用程序&…

Qt6.5安装教程——国内源

为什么离线包没了? Qt6开始非商业授权下,不再提供离线安装方式的exe,但源码安装费时费力,所以推荐安装方式已经为在线组件安装方式,包括vs2022、Qt在线安装工具已经成为开发工具新的安装趋势。 Qt是不是要放弃开源&…

【LeetCode: 56. 合并区间+贪心+双指针+标识+模拟】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

C#,《小白学程序》第六课:队列(Queue)的应用,《实时叫号系统》

医院里面常见的叫号系统怎么实现的&#xff1f; 1 文本格式 /// <summary> /// 下面定义一个新的队列&#xff0c;用于演示《实时叫号系统》 /// </summary> Queue<Classmate> q2 new Queue<Classmate>(); /// <summary> /// 《小白学程序》第…

CentOS 8 安装 Code Igniter 4

在安装好LNMP运行环境基础上&#xff0c;将codeigniter4文件夹移动到/var/nginx/html根目录下&#xff0c;浏览器地址栏输入IP/codeigniter/pulbic 一直提示&#xff1a; Cache unable to write to "/var/nginx/html/codeigniter/writable/cache/". 找了好久&…

图像颜色空间转换

目录 1.图像颜色空间介绍 RGB 颜色空间 2.HSV 颜色空间 3.RGBA 颜色空间 2.图像数据类型间的互相转换convertTo() 3.不同颜色空间互相转换cvtColor() 4.Android JNI demo 1.图像颜色空间介绍 RGB 颜色空间 RGB 颜色空间是最常见的颜色表示方式之一&#xff0c;其中 R、…

SQL注入之报错注入

文章目录 报错注入是什么&#xff1f;报错注入获取cms账号密码成功登录 报错注入是什么&#xff1f; 在注入点的判断过程中&#xff0c;发现数据库中SQL 语句的报错信息&#xff0c;会显示在页面中&#xff0c;因此可以利用报错信息进行注入。 报错注入的原理&#xff0c;就是在…

jwt安全问题

文章目录 jwt安全问题jwt简介jwt组成headerpayloadsignature 潜在漏洞空加密算法web346 密钥爆破web348 敏感信息泄露web349 **修改算法RS256为HS256**web350 jwt安全问题 jwt简介 JWT的全称是Json Web Token&#xff0c;遵循JSON格式&#xff0c;跨域认证解决方案&#xff0…

Vue.js2+Cesium1.103.0 十、加载 Three.js

Vue.js2Cesium1.103.0 十、加载 Three.js Demo ThreeModel.vue <template><divid"three_container"class"three_container"/> </template><script> /* eslint-disable eqeqeq */ /* eslint-disable no-unused-vars */ /* eslint…

unity VS无法进行断点调试

有时候我们的VS无法进行断点调试&#xff0c;报错如下&#xff1a; 原因是&#xff1a;开启了多个项目&#xff0c;vs无法找到调式项目 解决&#xff1a;点击菜单栏--调试----附加unity调试程序 会弹出一个框&#xff0c;然后选择你要调试的项目 即可

Android屏幕显示 android:screenOrientation configChanges 处理配置变更 代码中动态切换横竖屏

显示相关 屏幕朝向 https://developer.android.com/reference/android/content/res/Configuration.html#orientation 具体区别如下&#xff1a; activity.getResources().getConfiguration().orientation获取的是当前设备的实际屏幕方向值&#xff0c;可以动态地根据设备的旋…

vue2使用 vis-network 和 vue-vis-network 插件封装一个公用的关联关系图

效果图&#xff1a; vis组件库&#xff1a;vis.js vis-network中文文档&#xff1a;vis-network 安装组件库&#xff1a; npm install vis-network vue-vis-network 或 yarn add vis-network vue-vis-network 新建RelationGraph.vue文件&#xff1a; <template><…

写用例写的焦头烂额?看看摸鱼5年的老点工是怎么写的...

给你个需求&#xff0c;你要怎么转变成最终的用例&#xff1f; 直接把需求文档翻译一下就完事了。 老点工拿到需求后的标准操作&#xff1a; 第一步&#xff1a;解析需求 先解析需求-找出所有需求中的动词&#xff0c;再列出所有测试点。测试点过程不断发散&#xff0c;对于…

【Linux】centos8安装cmake3.27.4

第一步&#xff0c;去官网下安装包&#xff0c;一定不要下错了 下好了之后&#xff0c;用ftp软件传到云服务器或者虚拟机上&#xff0c;我用的是centos8系统&#xff0c;安装之前先准备好这些依赖项 yum install -y gcc gcc-c make automake yum install -y openssl openssl-…