安全初级—正则表达式、This关键字、闭包

文章目录

  • 正则表达式
      • 字面量字符
      • 元字符
      • 转义符
      • 特殊字符
      • 字符类
      • 预定义模式
      • 重复类
      • 量词符
      • 贪婪模式
      • 修饰符
  • This关键字
    • 使用场合
    • 使用注意点
      • 避免多层 this
      • 避免数组处理方法中的 this
      • 避免回调函数中的 this
    • 绑定 this 的方法
      • Function.prototype.call()
      • Function.prototype.apply()
      • Function.prototype.bind()
  • 闭包
      • 变量作用域
      • 读取函数内部的局部变量
      • 闭包概念

正则表达式

字面量字符

某个字符只表示它字面的含义,例如/a/匹配a/b/匹配b

元字符

(1)点字符(.)

点字符可以匹配除回车(\r)、换行(\n)、行分隔符(u2028)和段分隔符(\u2029)以外的所有字符。

同时,点字符对于码点大于0xFFFF字符也不能正确的匹配,会认为这是两个字符

c.t会匹配ct之间包含任意一个字符的情况,只要字符在同一行。

(2)位置字符

位置字符用来提示字符所处的位置,主要有两个字符。

  • ^ 表示字符串的开始位置
  • $ 表示字符串的结束位置
// test必须出现在开始位置
/^test/.test('test123') // true// test必须出现在结束位置
/test$/.test('new test') // true// 从开始位置到结束位置只有test
/^test$/.test('test') // true
/^test$/.test('test test') // false

(3)选择符(|

(|)表示“或关系”(or),即a|b匹配ab

多个选择符可以联合使用。

// 匹配fred、barney、betty之中的一个
/fred|barney|betty/

其他的元字符还包括\*+?()[]{}

转义符

正则表达式中,需要反斜杠转义的,一共有12个字符:^.[$()|*+?{\

这些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。

特殊字符

对于不能打印的特殊字符,正则表达式提供了表达方法

  • \cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
  • [\b] 匹配退格键(U+0008),不要与\b混淆。
  • \n 匹配换行键。
  • \r 匹配回车键。
  • \t 匹配制表符 tab(U+0009)。
  • \v 匹配垂直制表符(U+000B)。
  • \f 匹配换页符(U+000C)。
  • \0 匹配null字符(U+0000)。
  • \xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
  • \uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。

字符类

字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了

例如[abc] 表示abc之中任选一个匹配。

(1)脱字符(^)

如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。

例如[^abc] 表示abc之外都可以匹配。

如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。

点号作为元字符(.)是不包括换行符的

(2)连字符(-)

某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。

例如[123456789]可以写成[1-9],同理[A-Z]表示26个大写字母。

/a-z/.test('b') // false
/[a-z]/.test('b') // true

如果(-)中没有出现在[]中,就只是匹配字面的含义,不具备简写的作用。

只有当(-)用在[]之中,才表示连续的字符序列。

合法的字符类简写形式:

[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9-]
[1-31]  //不代表`1`到`31`,只代表`1`到`3`

连字符还可以用来指定 Unicode 字符的范围。

var str = "\u0130\u0131\u0132";
/[\u0128-\uFFFF]/.test(str)
// true

预定义模式

预定义模式指的是某些常见模式的简写方式

  • \d 匹配0-9之间的任一数字,相当于[0-9]
  • \D 匹配所有0-9以外的字符,相当于[^0-9]
  • \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
  • \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
  • \s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]
  • \S 匹配非空格的字符,相当于[^ \t\r\n\v\f]
  • \b 匹配词的边界。
  • \B 匹配非词边界,即在词的内部。

通常,正则表达式遇到换行符(\n)就会停止匹配。

重复类

模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

量词符

量词符用来设定某个模式出现的次数。

  • ? 问号表示某个模式出现0次或1次,等同于{0, 1}
  • * 星号表示某个模式出现0次或多次,等同于{0,}
  • + 加号表示某个模式出现1次或多次,等同于{1,}

贪婪模式

量词符默认情况下都是最大可能匹配,即匹配到下一个字符不满足匹配规则为止。这被称为贪婪模式。

var s = 'aaa';
s.match(/a+/) // ["aaa"]

非贪婪模式,即最小可能匹配。只要一发现匹配,就返回结果,不往下检查。

将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

var s = 'aaa';
s.match(/a+?/) // ["a"]

除了非贪婪模式的加号(+?),还有非贪婪模式的星号(*?)和非贪婪模式的问号(??)。

  • +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。
  • *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
  • ??:表格某个模式出现0次或1次,匹配时采用非贪婪模式。

修饰符

修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。

修饰符可以单个使用,也可以多个一起使用。

// 单个修饰符
var regex = /test/i;// 多个修饰符
var regex = /test/ig;

(1)g修饰符

正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。

var regex = /b/g;
var str = 'abba';regex.test(str); // true
regex.test(str); // true
regex.test(str); // false

因为字符串abba只有两个b,所以前两次匹配结果为true,第三次匹配结果为false

(2)i 修饰符

正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写。

/abc/.test('ABC') // false
/abc/i.test('ABC') // true

(3)m 修饰符

m修饰符表示多行模式(multiline),会修改^$的行为。默认情况下(即不加m修饰符时),^$匹配字符串的开始处和结尾处,加上m修饰符以后,^$还会匹配行首和行尾,即^$会识别换行符(\n)。

/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true

This关键字

this就是属性或方法“当前”所在的对象。

下面是一个实际的例子。

var person = {name: '张三',describe: function () {return '姓名:'+ this.name;}
};person.describe()
// "姓名:张三"

由于对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this的指向是可变的。

function f() {return '姓名:'+ this.name;
}var A = {name: '张三',describe: f
};var B = {name: '李四',describe: f
};A.describe() // "姓名:张三"
B.describe() // "姓名:李四"

函数f内部使用了this关键字,随着f所在的对象不同,this的指向也不同。

只要函数被赋给另一个变量,this的指向就会变。

使用场合

(1)全局环境

全局环境使用this,它指的就是顶层对象window

this === window // truefunction f() {console.log(this === window);
}
f() // true

(2)构造函数

构造函数中的this,指的是实例对象。

var Obj = function (p) {this.p = p;
};
//在构造函数obj,this指向p属性
var o = new Obj('Hello World!');
o.p // "Hello World!"

(3)对象的方法

如果对象的方法里面包含thisthis的指向就是方法运行时所在的对象。该方法赋值给另一个对象,就会改变this的指向。

var obj ={foo: function () {console.log(this);}
};obj.foo() // obj
//此时this指向obj
//以下的用法会改变this的指向
// 情况一
(obj.foo = obj.foo)() // window
// 等同于
(obj.foo = function () {console.log(this);
})()
// 等同于
(function () {console.log(this);
})()// 情况二
(false || obj.foo)() // window
//等同于
(false || function () {console.log(this);
})()// 情况三
(1, obj.foo)() // window
//等同于
(1, function () {console.log(this);
})()

使用注意点

避免多层 this

由于this的指向是不确定的,所以切勿在函数中包含多层的this

var o = {f1: function () {console.log(this);var f2 = function () {console.log(this);}();}
}o.f1()
// Object
// Window

这种情况,f1第一次指向对象o,然后代码运行到f2时,this的指向又变成了全局对象。

避免数组处理方法中的 this

数组的mapforeach方法,允许提供一个函数作为参数。这个函数内部不应该使用this

var o = {v: 'hello',p: [ 'a1', 'a2' ],f: function f() {this.p.forEach(function (item) {console.log(this.v + ' ' + item);});}
}o.f()
// undefined a1
// undefined a2

上面的this其实也是类似于多层this,函数f的调用也是相当于在全局环境下调用,所以这里的this指向也是指向window对象。

避免回调函数中的 this

回调函数中的this往往会改变指向,最好避免使用。

var o = new Object();
o.f = function () {console.log(this === o);
}// jQuery 的写法
$('#button').on('click', o.f);

以上的代码,在调用函数f时,是在按钮对象的环境下调用的,所以this的指向也不是o,而是指向按钮的DOM对象。

绑定 this 的方法

JavaScript 提供了callapplybind这三个方法,来切换/固定this的指向。

Function.prototype.call()

函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。

call方法的参数,应该是一个对象。如果参数为空、nullundefined,则默认传入全局对象。

var n = 123;
var obj = { n: 456 };function a() {console.log(this.n);
}//如果`call`方法没有参数,或者参数为`null`或`undefined`,则等同于指向全局对象。
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
//如果指向全局对象,返回结果为`123`
a.call(window) // 123
//如果使用`call`方法将`this`关键字指向`obj`对象,返回结果为`456`
a.call(obj) // 456

如果call方法的参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入call方法。

var f = function () {return this;
};f.call(5)  //5为参数,不是对象
// Number {[[PrimitiveValue]]: 5}

call方法还可以接受多个参数。

func.call(thisValue, arg1, arg2, ...)

Function.prototype.apply()

apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数,使用格式如下。

func.apply(thisValue, [arg1, arg2, ...])

(1)找出数组最大元素

JavaScript 不提供找出数组最大元素的函数。结合使用apply方法和Math.max方法,就可以返回数组的最大元素。

var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15

(2)将数组的空元素变为undefined

通过apply方法,利用Array构造函数将数组的空元素变成undefined

Array.apply(null, ['a', ,'b'])
// [ 'a', undefined, 'b' ]

(3)转换类似数组的对象

另外,利用数组对象的slice方法,可以将一个类似数组的对象(比如arguments对象)转为真正的数组。

Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
//前提:被处理的对象必须有`length`属性,以及相对应的数字键。

Function.prototype.bind()

bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。

var counter = {count: 0,inc: function () {this.count++;}
};var func = counter.inc.bind(counter);
func();
counter.count // 1//`counter.inc()`方法被赋值给变量`func`。这时必须用`bind()`方法将`inc()`内部的`this`,绑定到`counter`,否则就会出错。

bind()方法有一些使用注意点。

(1)每一次返回一个新函数

bind()方法每运行一次,就返回一个新函数,这会产生一些问题。

(2)结合回调函数使用

回调函数是 JavaScript 最常用的模式之一,但是一个常见的错误是,将包含this的方法直接当作回调函数。

(3)结合call()方法使用

利用bind()方法,可以改写一些 JavaScript 原生方法的使用形式。

闭包

闭包就是能够读取外层函数内部变量的函数

变量作用域

变量的作用域为两种:全局作用域和局部作用域

1)函数内部可以读取全局变量

2)函数外部无法读取函数内部的局部变量

读取函数内部的局部变量

1)在函数内部再定义一个函数

function f1() {let code = 200;function f2() {console.log(code);}
}

函数f1内部的函数f2可以读取f1中所有的局部变量。因此,若想在外部访问函数f1中的局部变量code,可通过函数f2间接访问。

2)为外部程序提供访问函数局部变量的入口

function f1() {let code = 200;function f2() {console.log(code);}return f2;
}f1()();  // 200

闭包概念

  • 闭包访问的变量,是每次运行上层函数时重新创建的,是相互独立的。

  • 不同的闭包,可以共享上层函数中的局部变量

使用闭包的注意点:

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

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

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

相关文章

LLaMA 2: Open Foundation and Fine-Tuned Chat Models

LLaMA 2: Open Foundation and Fine-Tuned Chat Models Pre-trainingFine-tuningReward modelRLHF参考 Pre-training 数据层面: 预训练语料比LLaMA1多了40%,一共2T tokens,更关注了高质量数据的清洗。 其中数据不包含Meta产品与服务&#xf…

PHP8的注释-PHP8知识详解

欢迎你来到PHP服务网,学习《PHP8知识详解》系列教程,本文学习的是《PHP8的注释》。 什么是注释? 注释是在程序代码中添加的文本,用于解释和说明代码的功能、逻辑或其他相关信息。注释通常不会被编译器或解释器处理,而…

论文笔记:Fine-Grained Urban Flow Prediction

2021 WWW 1 intro 细粒度城市流量预测 两个挑战 细粒度数据中观察到的网格间的转移动态使得预测变得更加复杂 需要在全局范围内捕获网格单元之间的空间依赖性单独学习外部因素(例如天气、POI、路段信息等)对大量网格单元的影响非常具有挑战性——>论…

draw up a plan

爱情是美好的,却不是唯一的。爱情只是属于个人化的感情。 推荐一篇关于爱情的美文: 在一个小镇上,有一家以制作精美巧克力而闻名的手工巧克力店,名叫“甜蜜之爱”。这家巧克力店是由一位名叫艾玛的年轻女性经营的,她对…

iOS - Apple开发者账户添加新测试设备

获取UUID 首先将设备连接XCode,打开Window -> Devices and Simulators,通过下方位置查看 之后登录(苹果开发者网站)[https://developer.apple.com/account/] ,点击设备 点击加号添加新设备 填写信息之后点击Continue,并一路继续…

靶机精讲之Brainpan1

nmap扫描 主机发现 端口扫描 服务扫描 -sT 说明用tcp协议(三次握手)扫描 -sV扫描版本 O扫描系统 NULL是图片 10000端口是个python服务 UDP扫描 脚本扫描 web渗透 目录爆破 显示/bin/目录有东西 gobuster dir -w /usr/share/dirbuster/wordlists/di…

蓝桥杯单片机第十届国赛 真题+代码

iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础&#xff0c;根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求&#xff0c;进行代码调试和修改。 */ #include <STC1…

【【51单片机DA转换模块】】

爆改直流电机&#xff0c;DA转换器 main.c #include <REGX52.H> #include "Delay.h" #include "Timer0.h"sbit DAP2^1;unsigned char Counter,Compare; //计数值和比较值&#xff0c;用于输出PWM unsigned char i;void main() {Timer0_Init();whil…

后台管理系统中刷新业务功能的实现

实现 下载vueuse npm i vueuse/core在header组件中引入并给全屏按钮绑定点击事件 <el-button type"default" click"toggle" icon"FullScreen" circle></el-button>import { useFullscreen } from vueuse/coreconst { toggle } u…

【Java】分支结构习题

【Java】分支结构 文章目录 【Java】分支结构题1 &#xff1a;数字9 出现的次数题2 &#xff1a;计算1/1-1/21/3-1/41/5 …… 1/99 - 1/100 的值。题3 &#xff1a;猜数字题4 &#xff1a;牛客BC110 X图案题5 &#xff1a;输出一个整数的每一位题6 &#xff1a; 模拟三次密码输…

[SQL挖掘机] - 内连接: inner join

介绍: 内连接是一种多表连接方式&#xff0c;用于将两个或多个表中的数据通过共同的列值进行匹配&#xff0c;并返回满足连接条件的匹配行。简单来说&#xff0c;内连接能够将相关联的数据组合在一起&#xff0c;以便进行更复杂和全面的数据分析。 内连接的工作原理如下&…

bash: 睡觉的冒号;是不是两个点?

文章目录 简介躺着的冒号是两个点正常冒号总结简介 在bash里冒号和躺着的冒号的用法不一样一定要注意别用错。 躺着的冒号是两个点 难道正常的不是两个点)的作用: A sequence expression takes the form {x…y[…incr]}, where x and y are either integers or single cha…

排序算法、

描述 由小到大输出成一行&#xff0c;每个数字后面跟一个空格。 输入 三个整数 输出 输入三个整数&#xff0c;按由小到大的顺序输出。 输入样例 1 2 3 1 输出样例 1 1 2 3 输入样例 2 4 5 2 输出样例 2 2 4 5 代码一&#xff08;如下&#xff09;&#xff1…

pytest+allure运行出现乱码的解决方法

pytestallure运行出现乱码的解决方法 报错截图&#xff1a; 这里的截图摘自 悟翠人生 小伙伴的https://blog.csdn.net/weixin_45435918/article/details/107601721一文。 这是因为没有安装allure运行环境或者没有配置allure的环境变量导致&#xff0c;解决方案&#xff1a; 1…

各系统的目录信息路径

Windows系统: 查看系统版本——C:\boot.ini IIS配置文件——C:\windows\system32\inetsrv\MetaBase.xml 存储Windows系统初次安装的密码——C:\windows\repair\sam Mysql配置——C:\ProgramFiles\mysql\my.ini MySQL root密码——C:\P…

LaTex使用技巧20:LaTex修改公式的编号和最后一行对齐

写论文发现公式编号的格式不对&#xff0c;要求是如果是多行的公式&#xff0c;公式编号和公式的最后一行对齐。 我原来使用的是{equation}环境。 \begin{equation} \begin{aligned} a&bc\\ &cd \end{aligned} \end{equation}公式的编号没有和最后一行对齐。 查了一…

CAN转EtherNet/IP网关can协议是什么意思

你是否曾经遇到过不同的总线协议难以互相通信的问题&#xff1f;远创智控的YC-EIP-CAN网关为你解决了这个烦恼&#xff01; 远创智控YC-EIP-CAN通讯网关是一款自主研发的设备&#xff0c;它能够将各种CAN总线和ETHERNET/IP网络连接起来&#xff0c;解决不同总线协议之间的通信…

SpringBoot项目部署在Windows与Centos上

文章目录 Windows部署一、github上下载文件winsw二、文件目录三、编辑xml文件四、安装服务五、启动服务六、把jar包放到项目外面七、添加限制内存 Linux部署一、准备二、服务三、操作 Windows部署 windows部署服务借鉴于此篇博文 一、github上下载文件winsw 点击链接下载下图…

uniapp使用HQChart的k线,用webSocket更新数据

项目&#xff1a;不借用HQChart的各种接口数据&#xff0c;即数据后端返回&#xff0c;但是数据格式要和原数据格式一样。 //k线图 CreateHQChartKLine(){var chartHeightuni.upx2px(this.ChartHeight);let hqchartCtrlthis.$refs.HQChartCtrl;hqchartCtrl.KLine.Option.Type&…

【触觉智能Purple Pi OH开发板体验】开箱体验:开源主板Purple Pi RK3566 上手指北

前言 前段时间收到来自【电子发烧友】的一款开发板&#xff0c;名叫&#xff1a;PurplePi&#xff0c;216G售价仅249元。它使用的芯片是rk3566&#xff0c;适配的OpenHarmony版本为3.2 Release 是目前最便宜的OpenHarmony标准系统开源开发板&#xff0c;并且软硬件全部开源&am…