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

news2024/12/22 23:56:46

目录

  • 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 = firstName
  obj.lastName = lastName
  obj.fullName = firstName + lastName
  obj.myName = function () {
    console.log(obj.fullName)
  }
  return obj
}

const person = createPerson('张', '三')

通过构造函数创建对象

function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
  this.fullName = firstName + lastName
  this.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 = a
  this.b = b
  this.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 = a
  this.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) {
    // 过滤掉 print
    if (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 = true

var 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 = name
  this.pwd = pwd
}

User.prototype.playFreeVideo = function() {
  console.log('免费视频');
}

function VipUser(name, pwd, expires) {
  this.name = name
  this.pwd = pwd
  this.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.coloradmin.cn/o/950707.html

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

相关文章

异步迭代器

一、什么是异步迭代器? 实现了 __aiter__() 和 __anext__() 方法的对象。__anext__ 必须返回一个 awaitable对象。async for 会处理异步迭代器的 __anext__() 方法所返回的可等待对象,直到其引发一个 StopAsyncIteration 异常。 二、实例 class Async…

Python - functools.partial设置回调函数处理异步任务基本使用

一. 前言 在Python中,回调函数是指在一个函数执行完成后,调用另一个函数的过程。通常情况下,回调函数作为参数传递给原始函数,原始函数在执行完自己的逻辑后,会自动调用回调函数并将结果作为参数传递给它。 二. 回调…

知了汇智承办网信人才培训活动第二期,助力数字化网安人才储备

在数字经济时代,随着信息化的快速发展和互联网的深度应用,网络信息安全问题日益突出,成为制约数字经济健康发展的重要因素。为了有效提升网络安全人才的专业素质和技术能力,保障国家信息安全。知了汇智作为数字产教融合基地&#…

学习JAVA打卡第四十七天

日期的格式化 程序可能希望按照某种习惯来输出时间。例如时间的顺序:年/月/日或年/月/日/时/分/秒。可以直接使用String类调用format方法对日期进行格式化。 Format方法 Format方法: format(格式化模式,日期列表) 按照“格式…

FFT代码上的实现细节

ω \omega ω 的计算 ω n 1 \omega_n^1 ωn1​ 的计算 考虑单位圆, ω n 1 \omega_n^1 ωn1​ 为: 也就是: 注:op为判断当前为dft还是idft ω n i \omega_n^i ωni​ 的计算 当要计算 ω n i \omega_n^i ωni​ 时&#xf…

NSS [NUSTCTF 2022 新生赛]Ezjava1

NSS [NUSTCTF 2022 新生赛]Ezjava1 题目描述:你能获取flag{1}吗 开题,一眼java web中的index.jsp。 默认index.jsp中的body内容是$END$ 附件jar包导入IDEA,会自动反编译。看看源码。 附件结构大致如此。主要看classes.com.joe1sn中的代码就…

一篇掌握高级交换技术原理与配置(三):QINQ

一、概述 随着以太网技术在网络中的大量部署,利用VLAN对用户进行隔离和标识受到很大限制。因为IEEE802.1Q中定义的VLAN Tag域只有12个比特,仅能表示4096个VLAN,无法满足城域以太网中标识大量用户的需求,于是QinQ技术应运而生。 …

远程管理通道安全SSH协议主机验证过程

可以使用SSH协议进行远程管理通道安全保护,其中涉及的主要安全功能包括主机验证、数据加密性和数据完整性保护。 这里要注意的是【主机验证】和【身份验证】的区别,主机验证是客户端确认所访问的服务端是目标访问对象,比如从从客户端A(192.16…

企业微信cgi-bin/gateway/agentinfo接口存在未授权访问漏洞 附POC

文章目录 企业微信cgi-bin/gateway/agentinfo接口存在未授权访问漏洞 附POC1. 企业微信cgi-bin/gateway/agentinfo接口简介2.漏洞描述3.影响版本4.fofa查询语句5.漏洞复现6.POC&EXP7.整改意见8.往期回顾 企业微信cgi-bin/gateway/agentinfo接口存在未授权访问漏洞 附POC 免…

8天长假快来了,Python分析【去哪儿旅游攻略】数据,制作可视化图表

目录 前言环境使用模块使用数据来源分析 代码实现导入模块请求数据解析保存 数据可视化导入模块、数据年份分布情况月份分布情况出行时间情况费用分布情况人员分布情况 前言 2023年的中秋节和国庆节即将来临,好消息是,它们将连休8天!这个长假…

iptables教程

iptables netfilter/iptables(简称iptables)是与2.4.x和2.6.x系列版本Linux内核集成的IP信息包过滤系统。 Iptables Tutorial 1、表和链 1.1、表 iptables会根据不同的数据包处理功能使用不同的规则表。它包括如下五个表:filter、nat和m…

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

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

Revit SDK:SetParameterValueWithImageData 用图片像素值设置族实例参数值

前言 这个例子通过从图片中获取颜色,将颜色转换成数值,赋值给分割表面上对应族实例的对应参数。 内容 获取颜色的代码: Bitmap image new Bitmap(doc.PathName "_grayscale.bmp"); System.Drawing.Color pixelColor new Syst…

设计模式--迭代器模式(Iterator Pattern)

一、什么是迭代器模式 迭代器模式(Iterator Pattern)是一种行为型设计模式,用于提供一种统一的方式来访问一个聚合对象中的各个元素,而不需要暴露该聚合对象的内部结构。迭代器模式将遍历集合的责任从集合对象中分离出来&#xf…

MyBatisx代码生成

MyBatisx代码生成 1.创建数据库表 CREATE TABLE sys_good (good_id int(11) NOT NULL,good_name varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,good_desc varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (good_id) ) ENGINEInnoDB DEFAULT CHA…

[C/C++]函数的栈空间(避免栈空间溢出)

个人主页:北海 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏✨收录专栏:C/C🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!&#x1f9…

C++八股记录

C内存管理 C中,内存分成5个区。 栈:函数内局部变量;自动管理,效率高,但空间较小; 堆:new分配的内存块;手动管理,效率低,但空间大; 自由存储区&…

ScottPlot图标控件的使用

效果图 控件获取方法 Nugget ScottPlot.WinForms 参考代码 Form1.Designer.cs namespace ScottplotDemo {partial class Form1{/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.IContainer components null;/// <summary…

《动手学深度学习》-57长短期记忆网络LSTM

沐神版《动手学深度学习》学习笔记&#xff0c;记录学习过程&#xff0c;详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 长短期记忆网络&#xff08;LSTM&#xff09; 长期以来&#xff0c;隐变量模型存在长期信息保存和短期输入缺失的问题。解决这一问题的最早…

bazel入门学习笔记

简介 Bazel Google开源的&#xff0c;是一款与 Make、Maven 和 Gradle 类似的开源构建和测试工具。 它使用人类可读的高级构建语言。Bazel 支持多种语言的项目&#xff0c;可为多个平台构建输出。Bazel支持任意大小的构建目标&#xff0c;并支持跨多个代码库和大量用户的大型代…