一天一个js知识

原型继承和class继承

class:js中并不存在类的概念,class只是语法糖,本质还是函数;

提升&暂时性死区

console.log(a)// ƒ a() {}
var a=8
function a(){}
复制代码

1、这里说明函数的提升要优先于变量的提升;函数提升会把整个函数挪到作用域顶部,变量提升只会把声明挪到作用域顶部

2、如果把函数代码删掉,把var变成let,则会报错a is not defined这时候的报错则是因为暂时性死区的原因导致,我们不能在声明前就使用变量;

疑问:为什要有提升这个东西? 存在原因:其实提升存在的根本原因就是为了解决函数间互相调用的情况

原型

每个对象当我们打印的时候下面都会有个__proto__属性,该属性指向了原型,原型也是一个对象,且这个对象包含了很多的函数,还有一个 constructor属性,也就是构造函数,打开 constructor 属性我们又可以发现其中还有一个 prototype 属性,并且这个属性对应的值和先前我们在 proto 中看到的一模一样。所以我们又可以得出一个结论:原型的 constructor 属性指向构造函数,构造函数又通过 prototype 属性指回原型,但是并不是所有函数都具有这个属性,Function.prototype.bind() 就没有这个属性。

总结: Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它 Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它 函数的 prototype 是一个对象 对象的 proto 属性指向原型, proto 将对象和原型连接起来组成了原型链

浅拷贝&&深拷贝

浅拷贝:

1、const obj=Object.assign(target,...sources)将sources对象的所有属性值拷贝到target对象上,实现的是浅拷贝,改变sources的属性值,obj不会发生改变

2、通过展开运算符 ... 来实现浅拷贝

let b={...a}
//这时改变a的属性值b也不会改变
复制代码

浅拷贝只解决了第一层的问题,如果目标对象的值中还有对象的话,那么就又回到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使用深拷贝了。

深拷贝: 1、通过 JSON.parse(JSON.stringify(object)) 来实现深拷贝

let b = JSON.parse(JSON.stringify(a))
复制代码

但是此方法会忽略 undefined和symbol、不能序列化函数、不能解决循环引用的对象

2、使用new MessageChannel()

function structuralClone(obj) {return new Promise(resolve => {const { port1, port2 } = new MessageChannel()port2.onmessage = ev => resolve(ev.data)port1.postMessage(obj)})
}var obj = {a: 1,b: {c: 2}
}obj.b.d = obj.b// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => {const clone = await structuralClone(obj)console.log(clone)
}
test()
复制代码

bind(),call(), apply()

前面讲到了this指向 那么这次就说说改变this指向的三个方法

bind方法是用于创建一个函数,使这个函数不论怎么调用都有同样的this,该方法返回一个新函数,你必须调用它才会生效,参数跟call一样第一个是this,参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面

call与bind的区别就是它返回的是一个执行结果不需要调用

apply它与call的区别是第二个参数接受的是一个数组

以上三个的参数都没有限制可以是各种类型

bind()函数内部怎么实现的:

Function.prototype.myBind=function(context){if(typeof this!=='function'){throw new TypeError('err')}const _this=thisconst args=[...arguments].slice(1)//返回一个函数return F(){//最后来说通过 new 的方式,在之前的章节中我们学习过如何判断 //this,对于 new 的情况来说,不会被任何方式改变 //this,所以对于这种情况我们需要忽略传入的 thisif(this instanceof F){return new _this(...args,...arguments)}//对于直接调用来说,这里选择了 apply //的方式实现,但是对于参数需要注意以下情况:因为 bind //可以实现类似这样的代码 f.bind(obj, //1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现 //args.concat(...arguments)return _this.apply(context,args.concat(...arguments))}
}
复制代码

call()函数内部怎么实现的:

Function.prototype().myCall=function(context){if(typeoof this!=='function'){throw new TypeError('err')}context=context||window //context是可选参数,不传默认windowcontext.fn=this //给context创建fn属性,并将值设置为需要调用的函数const args=[...arguments].slice(1)//因为call可以传入多个参数,需要将参数剥离出来const resule=context.fn(...args)//调用函数delete context.fn//调用完后删除对象上的函数return result
}
复制代码

apply()函数内部怎么实现的:

Function.prototype.myApply = function(context) {if (typeof this !== 'function') {throw new TypeError('Error')}context = context || windowcontext.fn = thislet result// 处理参数和 call 有区别if (arguments[1]) {result = context.fn(...arguments[1])} else {result = context.fn()}delete context.fnreturn result
}
复制代码

this指向

对于this指向很多人都会混淆,其实很多网上把它说负复杂了看以下场景:

function foo(){console.log(this)
}
foo()
let num=1
const obj={num:1,foo:foo
}
obj.foo()
const c=new foo()
复制代码

传一张最近看的小册的老哥画的图,贼稳

instanceof

类似于typeof判断数据类型,因为起内部机制是通过原型链来判断的所以要更加严谨,但是对于原始类型想直接通过instanceof来判断是不行的,但是我们还是有办法让它判断原始类型的代码如下:

class   PrimitiveString{static [symbol.hasInstance(x){return typeof x=='string'}]
}
console.log('hello' instanceof PrimitiveString) //true
复制代码

typeof()

typeof()对于原始数据类型:number,string,boolean,symbol(es6引入的新的数据类型表示第一无二的值)除了null都可以显示正确类型,除了null,对于对象来说除了function都会返回object,所以此方法并不能正确返回数据类型

every()

用于检测数组中的所有元素是否都符合指定条件 every() 方法使用指定函数检测数组中的所有元素: 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。 如果所有元素都满足条件,则返回 true。 注意: every() 不会对空数组进行检测。 注意: every() 不会改变原始数组。 example1:数组中的元素是否满足大于等于4

let arr=[12,4,56,78,90]
let boolean=arr.every(item=>item>=4)//true
复制代码

map

map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。 传递给map()的函数的调用方式和传递给forEach()的函数的调用方式一样。但传递给map()的函数应该有返回值。注意:map()返回的是新数组:它不修改调用 的数组。

function square(arr){return arr.map(function(item){return item*item})
}
let arr=[1,2,3,4,5,6]
let arr2=square(arr)
console.log(arr2) //[1, 4, 9, 16, 25, 36]
复制代码

includes

与ES5中的indexOf类似,indexOf用来查找某个元素在数组中的位置有则返回元素位置索引,没有则返回-1,但是不能判断是否有NaN的元素;ES6中提供了Array.inclides()此方法只返回true和false即包含不包含,不能定位元素可判断NaN,可两个结合使用。 Array.inclides()的第二个参数表示判断的起始位置,若为负数表示从右起第几个但是不改变判断方向。

filter:

用于把Array的某些元素过滤掉返回剩下的元素,参数接受一个函数,函数作用于每一个元素,根据返回值是true或false决定保留还是丢弃该元素。filter是一个高阶函数关键在于正确实现一个筛选函数。 filter()接收的回调函数有三个,第一个是表示某个元素,第二个表示位置,第三个表示数组本身

example1:数组去重

letr,arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
r = arr.filter(function (element, index, self) {return self.indexOf(element) === index;
});
复制代码

去除重复元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉了。

example2:a数组中删除b数组中的元素

let a=[1,2,3,4,5,6],b=[1,2,3];
let c=a.filter(item=>!b.includes(item))
console.log(c) //[4,5,6]
复制代码

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

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

相关文章

构建图像金字塔_我们如何通过转移学习构建易于使用的图像分割工具

构建图像金字塔Authors: Jenny Huang, Ian Hunt-Isaak, William Palmer作者: 黄珍妮 , 伊恩亨特伊萨克 , 威廉帕尔默 GitHub RepoGitHub回购 介绍 (Introduction) Training an image segmentation model on new images can be daunting, es…

PHP mongodb运用,MongoDB在PHP下的应用学习笔记

1、连接mongodb默认端口是:27017,因此我们连接mongodb:$mongodb new Mongo(localhost) 或者指定IP与端口 $mongodb new Mongo(192.168.127.1:27017) 端口可改变若mongodb开启认证,即--auth,则连接为: $mongodb new …

a标签

a标签定义超链接&#xff0c;用于从一张页面链接到另一张页面&#xff0c;它最重要的属性是 href 属性&#xff0c;它指示链接的目标。 <a href"http://www.w3school.com.cn">W3School</a> 最常用的就像这样添加一个链接&#xff0c;如果是点击事件的话&…

MFC程序执行过程剖析

一 MFC程序执行过程剖析 1&#xff09;我们知道在WIN32API程序当中&#xff0c;程序的入口为WinMain函数&#xff0c;在这个函数当中我们完成注册窗口类&#xff0c;创建窗口&#xff0c;进入消息循环&#xff0c;最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数。而…

CF888E Maximum Subsequence(meet in the middle)

给一个数列和m&#xff0c;在数列任选若干个数&#xff0c;使得他们的和对m取模后最大&#xff08; \(1<n<35\) , \(1<m<10^{9}\)&#xff09; 考虑把数列分成两份&#xff0c;两边分别暴力求出所有的可能&#xff0c;那么对于一个数列中每一个数字\(x\)&#xff0…

virtualbox php mac,详解mac下通过docker搭建LEMP环境

在mac下通过docker搭建LEMP环境境1.安装virtualbox。由于docker是在lxc环境的容器2.安装boot2docker&#xff0c;用于与docker客户端通讯> brew update> brew install docker> brew install boot2docker3.初始化boot2docker&#xff0c;也就是在virtualbox上安装一个d…

SpringBoot项目打war包部署Tomcat教程

一、简介 正常来说SpringBoot项目就直接用jar包来启动&#xff0c;使用它内部的tomcat实现微服务&#xff0c;但有些时候可能有部署到外部tomcat的需求&#xff0c;本教程就讲解一下如何操作 二、修改pom.xml 将要部署的module的pom.xml文件<packaging>节点设置为war <…

在VS2005中使用添加变量向导十分的

在VS2005中使用添加变量向导十分的方便&#xff0c;但是如何手动添加呢。可以分为2步&#xff1a; 1. 在控件对应的类的头文件中添加相应的变量声明&#xff08;如&#xff1a;CString m_strResult&#xff09; 2. 在类的实现文件中的DoDataExchange(CDataExchange* pDX)函数…

关于如何使用xposed来hook微信软件

安卓端 难点有两个 收款码的生成和到帐监听需要源码加 2442982910转载于:https://www.cnblogs.com/ganchuanpu/p/10220705.html

GitHub动作简介

GitHub Actions can be a little confusing if you’re new to DevOps and the CI/CD world, so in this article, we’re going to explore some features and see what we can do using the tool.如果您是DevOps和CI / CD领域的新手&#xff0c;那么GitHub Actions可能会使您…

java returnaddress,JVM之数据类型

《Java虚拟机规范》阅读笔记-数据类型1.概述Java虚拟机的数据类型可分为两大类&#xff1a;原始类型(Primitive Types&#xff0c;也称为基本类型)和引用类型(Reference Types)。Java虚拟机用不同的字节码指令来操作不同的数据类型[1] 。2.原始类型原始类型是最基本的元素&…

C# matlab

编译环境&#xff1a;Microsoft Visual Studio 2008版本 9.0.21022.8 RTMMicrosoft .NET Framework版本 3.5已安装的版本: ProfessionalMicrosoft Visual Basic 2008 91986-031-5000002-60050Microsoft Visual Basic 2008Microsoft Visual C# 2008 91986-031-5000002-60050…

洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]

题目传送门 棘手的操作 题目描述 有N个节点&#xff0c;标号从1到N&#xff0c;这N个节点一开始相互不连通。第i个节点的初始权值为a[i]&#xff0c;接下来有如下一些操作&#xff1a; U x y: 加一条边&#xff0c;连接第x个节点和第y个节点A1 x v: 将第x个节点的权值增加vA2 x…

基于容器制作镜像

一。镜像基础 一。基于容器制作镜像 1. 查看并关联运行的容器 [ghlocalhost ~]$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4da438fc9a8e busybox …

照顾好自己才能照顾好别人_您必须照顾的5个基本数据

照顾好自己才能照顾好别人I am pretty sure that on your data journey you came across some courses, videos, articles, maybe use cases where someone takes some data, builds a classification/regression model, shows you great results, you learn how that model wo…

matlab数字仿真实验,DVR+备用电源自动投入的MATLAB数字仿真实验仿真实验

一、动态电压恢复器(DVR)的数字仿真实验动态电压恢复器(Dynamic Voltage Restorer&#xff0c;DVR)是一种基于电力电子技术的串联补偿装置&#xff0c;通常安装在电源与敏感负荷之间&#xff0c;其作用在于&#xff1a;保证电网供电质量&#xff0c;补偿供电电网产生的电压跌落…

c#,xp系统,Matlab6.5

编译环境&#xff1a;c#&#xff0c;xp系统&#xff0c;Matlab6.5 新建一个窗体项目&#xff0c;添加matlab引用。 然后试了四种方式调用matlab&#xff1a; 第一种 view plaincopy to clipboardprint?MLApp.MLAppClass matlab new MLApp.MLAppClass(); matlab.Visible 1;…

java script 对象

java script 对象 1.创建方式 1&#xff09;通过字面量的形式创建 例&#xff1b;var stt{x:1,y:2,y:3}; 或&#xff1b;var stt{ x:1, y:2, for:3 } 注意关键字必须放到引号中间 2&#xff09;通过new创建对象 例&#xff1a;var new stt(); stt.name 小鱼; stt.age 20…

认识数据分析_认识您的最佳探索数据分析新朋友

认识数据分析Visualization often plays a minimal role in the data science and model-building process, yet Tukey, the creator of Exploratory Data Analysis, specifically advocated for the heavy use of visualization to address the limitations of numerical indi…

架构探险笔记10-框架优化之文件上传

确定文件上传使用场景 通常情况下&#xff0c;我们可以通过一个form&#xff08;表单&#xff09;来上传文件&#xff0c;就以下面的“创建客户”为例来说明&#xff08;对应的文件名是customer_create.jsp&#xff09;&#xff0c;需要提供一个form&#xff0c;并将其enctype属…