查漏补缺 - 构造函数,原型,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将参数保存…

C++ 组合类

所谓组合类便是一个类中含有其他类的对象: #include <iostream> #include <string.h> using namespace std;class dog { public:dog() {}dog(const char *n, int age, const char *v) : age(age){strcpy(this->name, n);strcpy(this->var, v);}// 显示这条狗…

PG 权限实例

如果角色已经存在, 可以采用如下方法进行删除 psql -U pgsql -d postgresreassign owned by r_read to pgsql; drop owned by r_read; drop user if exists r_read;reassign owned by r_read_write to pgsql; drop owned by r_read_write; drop user if exists r_read_write;…

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

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

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

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

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

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

ASP.NET Core 的日志系统

ASP.NET Core 提供了丰富日志系统。 可以通过多种途径输出日志&#xff0c;以满足不同的场景&#xff0c;内置的几个日志系统包括&#xff1a; Console&#xff0c;输出到控制台&#xff0c;用于调试&#xff0c;在产品环境可能会影响性能。Debug&#xff0c;输出到 System.Di…

浅析编程中的语法糖

1、理解语法糖 1.1.什么是语法糖&#xff1f; 语法糖是一种编程语言的特性&#xff0c;它并不引入新功能&#xff0c;而是通过提供更简洁、易读的语法形式&#xff0c;使代码编写和理解变得更加轻松。它有点像是一种“甜蜜”的语法&#xff0c;让我们在不改变底层逻辑的情况下…

037 - 有关时间和日期的函数方法

文档&#xff1a;MySQL :: MySQL 5.7 Reference Manual :: 12.7 Date and Time Functions​​​​​​ 以下为案例&#xff0c;更多内容可查看文档 返回当前日期&#xff1a; CURDATE() 返回当前时间&#xff1a; CURTIME() 返回当前日期和时间&#xff1a; NOW() 返回年份&a…

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

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

【2023】LeetCode HOT 100——链表

目录 1. 相交链表1.1 C++实现1.2 Python实现1.3 时空分析2. 反转链表2.1 C++实现2.2 Python实现2.3 时空分析3. 回文链表3.1 C++实现3.2 Python实现3.3 时空分析4. 环形链表4.1 C++实现4.2 Python实现4.3 时空分析5. 环形链表 II5.1 C++实现5.2 Python实现

Jupyter installation Tutorial

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

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

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

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

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

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…