var a = 1;
var foo = {
a: 2,
bar: function () {
return this.a;
}
};
console.log(foo.bar()); //2
console.log((foo.bar)()); //2
console.log((foo.bar=foo.bar)()); //1
“匿名函数的执行环境具有全局性”,所以最里层那个函数中this指向全局环境,全局环境没有定义foo变量所以输出undefined。在匿名函数外部将this保存到一个内部函数可以访问的变量self中,可以通过self访问这个对象,所以self.foo为bar
var myobject = {
foo: “bar”,
func: function () {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function () {
console.log(this.foo);//undefined
console.log(self.foo);//bar
})();
}
};
myobject.func();
改变this指向
JavaScript为我们专门提供了一些函数方法来帮助我们处理函数内部this指向问题,常用的有bind()、call()、apply()
三种方法
1.call()
前面讲过,call的主要作用可以实现继承
var obj = {
a:1
}
function f(){
console.log(this);
}
f.call(obj)
//call 第一个可以调用函数,还可以改变函数类this指向
//call 主要作用可以实现继承
2.apply()
方法调用一个函数,简单理解为调用函数的方式,但是它可以改变this的指向
fun.apply(thisArg, [argsArray])
thisArg:在函数执行时指定的this对象
argsArray: 传递的值,必须包含在数组(伪数组)里面
返回值为函数的返回值,因为它就是调用函数
应用方面:apply传递数组参数,所以可以借助数学内置对象求最大值 Math.max.apply(Math,arr)
var arr = [1,66,199,5,6]
//console.log(Math.max.apply(null,arr));
//严格模式,最好让thisArg指向Math
console.log(Math.max.apply(Math,arr));
//求数组最大值的其他方法
var ma = Math.max(…arr);
(es6拓展运算符…Math.max(...arr)
也可以,但是不能 MAth.max(arr)
,因为max不接受数组,只接受一个一个的参数)
3.bind()
方法不会调用函数
,但是能改变函数内部this指向
fun.bind(thisArg, arg1, arg2…)
返回指定this值和初始化参数改造的原函数拷贝
即创造新的函数 var f = fn.bind(xx)
应用方面:定时器等不想立即调用的函数(或者处理其他只能用that来暂时储存对象的情况)
//场景:点击按钮后,禁用按钮。3秒后恢复
btn.onclick = function() {
this.disabled = true;
//old way:
var that = this;
setTimeout(function() {
that.disabled = false;
}, 3000)
//new way:
setTimeout(function() {
this.disabled = false;
}.bind(this), 3000) //这个this指向btn
}
巧妙运用: 传参的时候可以传递其他对象过来
call、apply、bind总结
相同
:改变函数内部的this指向。
区别
:
-
call和apply会调用函数,bind不调用但返回一个改造过this的函数。
-
call和bind传参为aru1,aru2…形式,apply必须数组形式[arg]
应用
:
-
call经常做继承
-
apply经常与数组有关系,比如借助数学对象求数组的最大值
-
bind不调用函数,但想改变this指向,如定时器的内部this指向
ie10以上版本才支持 它是让JavaScript以严格的条件下运行代码
-
消除了JavaScript一些语法不严谨的地方,减少怪异行为
-
消除代码一些不安全之处,保证代码运行的安全
-
提高编译器效率,增加运行速度
-
禁用了ECMAscript在未来版本中可能会定义的一些语法,为未来JavaScript做好铺垫,比如class、enum、super等
开启严格模式
应用到整个到整个脚本或个别函数中,因此,我们可以讲严格模式分为脚本开启严格模式
和为函数开启严格模式
两种情况
为脚本开启严格模式:
方法二:(写在立即执行函数里的都要按照严格模式)
为函数开启严格模式:(只在此函数内部有严格模式)
变化
-
严格模式禁止变量为声明就赋值
-
严禁删除已声明的变量,比如
delete x;
是错误的 -
在严格模式下,全局作用域中函数中的this不再是window,而是
undefined
(但是定时器之类的还是指向window) -
严格模式下,如果构造函数不配合new来使用,this就会报错
-
函数不能有重名参数
-
函数必须声明在顶层,因为新版本的JavaScript引入了块级作用域,所以不允许在非函数代码块内声明函数
高阶函数是对其它函数进行操作的函数,它接收函数作为参数
或将函数作为返回值
输出,最典型的就是作为回调函数
function fn(a, b, callback) {
console.log(a + b);
callback && callback();
}
fn(1, 2, function(){
console.log(‘我是callback’);
})
闭包指有权访问另外一个函数作用域中变量的
函数,简单理解就是一个作用域可以访问另外一个函数内部的局部变量
(被访问作用域的函数就是闭包函数)
//在此处fun函数作用域访问了另外一个函数fn里面的局部变量num,形成了闭包,此时fn就是一个闭包函数
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
在fn外部作用域访问fn内部局部变量(它返回了当时的作用域):
//所以闭包就是典型的高阶函数
function fn() {
var num = 10;
return function() {
console.log(num)
}
}
var f = fn();
f();
闭包的主要作用:延伸了变量的作用范围
利用闭包解决异步问题:
(因为函数是一个作用域)
场景:打印li当前索引(面试可能问)
立即执行函数也成为了小闭包,因为立即执行函数里面任何一个函数都可以使用它的i变量
- 55
- 66
- 77
- 88
回调函数:获取异步操作的
结果
一般情况下,把函数作为参数的目的就是为了获取函数内部的异步操作的结果
//如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取
function fn(callback) {
setTimeout(function () {
var data = ‘hello’;
callback(data);
}, 1000)
}
fn(function (data) {
console.log(data);
})
如果一个
函数在内部可以调用其本身
,则这个函数是递归
(俄罗斯套娃)但是容易发生“栈溢出”错误,所以必须加退出条件“return”
浅拷贝和深拷贝
(jQuery篇目有提及到(
$.extend([deep], target, object1, [objectN])
))-
浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
-
深拷贝拷贝多层,每一级别的数据都会拷贝
ES6中浅拷贝的语法糖:
Object.assign(target, ...source)
(把source拷贝给target)利用循环写浅拷贝
var obj = {
id: 1,
name: ‘andy’,
msg: {
age: 18
}
};
var o = {};
for (var k in obj) {
// k是属性名, obj[k]是属性值
o[k] = obj[k];
}
//使用assign拷贝
Object.assign(o,obj); 把obj拷贝给o
利用递归写深拷贝
var obj = {
id: 1,
name: ‘andy’,
msg: {
age: 18
}
};
var o = {};
function deepcopy(newobj, oldobj) {
for(var k in oldobj) {
// 获取属性值
var item = oldobj[k];
// 判断该值是否属于数组(数组也属于object,所以要先写)
if(item instanceof Array) {
newobj[k] = [];
deepcopy(newobj[k], item);
} else if(item instanceof Object) {
// 判断该值是否为对象
newobj[k] = {};
deepcopy(newobj[k], item);
} else {
// 所以剩下的属于简单数据类型
newobj[k] = item;
}
}
}
deepcopy(o, obj);
console.log(o);
概述
正则表达式(regular expression)是用于匹配字符串中字符组合的模式,在JavaScript中,
正则表达式也是对象
-
正则表达式通常用来做检索,替换那些符合某个模式(规则)的文本,例如昵称输入框里的对中文的匹配;
-
此外,正则表达式还常用于过滤掉页面一些敏感(替换),或者从字符串获取我们想要的特定部分(提取)等
特点
:-
灵活性、逻辑性、功能性非常强
-
可以迅速用极简的形式达到对字符串复杂的控制
-
对刚接触的人来说,比较晦涩难懂
-
一般实际开发,都是直接复制写好的正则表达式,但是要求会使用正则表达式且根据实际情况修改正则表达式
应用
1.通过调用RegExp对象的构造函数创建
var 变量名 = new RegExp(/表达式/)
2.通过字面量创建
var 变量名 = /表达式/
(正则表达式不需要加引号,不管是数字型还是字符串型)测试正则表达式是否符合语法规范:
test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回true或false,
其参数是测试字符串
regexObj.test(str)
(只要包含有str这个字符串,返回的都是true)var rg = /123/;
console.log(rg.test(123)); //true
console.log(rg.test(12123)); //true
特殊字符
一个正则表达式可以由简单的字符构成,比如/abc/, 也可以是简单和特殊字符串的组合,比如/ab*c/。其中特殊字符也被称为元字符,在正则表达式中具有特殊意义的专用符号,如^ 、$ 、+ 等
(匹配特殊字符前面增加
\
就可以了)正则表达式速查表
:正则表达式速查边界符
:^
表示匹配行首的文本(以谁开始)$
表示匹配行尾的文本(以谁结束)var rg = /^abc/;
console.log(rg.test(‘abcd’)); //true
console.log(rg.test(‘babc’)); //false
//必须是abc,类似全等
var rg2 = /^abc$/;
console.log(rg.test(‘abcd’)); //false
console.log(rg.test(‘abcabc’)); //false
字符类
:[]
表示有一系列字符可供选择,只要匹配到其中一个就可以了var rg = /[abc]/; //只要包含有a或者b或者c就返回true
console.log(rg.test(‘andy’)); //返回true
//var rg = /1$/ 是三选一,只有是单个a或者b或者c才返回true
[]
使用范围符号
-var rg = /2$/; //26个英文小写字母任何一个字母都返回true
var rg1 = /3$/; //26个英文字母任何一个字母都返回true
var rg2 = /4$/; //任何单个26小写字母,0-9数字,_, -,都返回true
[]
里使用^:如果中括号里有^
表示取反的意思,千万别和边界符^
混淆,要区分开来var rg = /[a-z]$/; //26个英文小写字母任何一个字母都返回false
量词符
:用来设定某个模式出现的次数,有*
、+
、?
、{}
,{}
的量词间不要有空格,可以用test来检测下方正则表达式var rg = /^a*$/; //a可以出现0-n次,n>=0
var rg1 = /^a+$/; //a可以出现1-n次,n>=1
var rg2 = /^a?$/; //a可以出现1或0次
var rg3 = /^a{3}$/; //a只能可以出现3次
var rg4 = /^a{3,}$/; //a只可以出现3-n次 n>=3
var rg5 = /^a{3,16}$/; //a只可以出现3-16次
//普遍的用户名规定:
var name = /5{6, 16}$/
括号总结
[]
中括号:字符集合,匹配方括号中的任意字符{}
大括号:量词符,里面表示重复次数,但只让大括号前面一个字符重复 (注意:/^abc{3}$/
,只让c重复三次,即abccc)()
小括号:表示优先级 可以用来:/^(abc){3}$/
,表示让abc重复三次,即abcabc预定义类
\d
匹配到0-9任意一数字,相当于[0-9]
(var rg = /\d/;
)\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]正则里的或者符号:
|
(var rg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
)正则替换
replace()方法可以实现替换字符串的操作,用来替换的参数可以是一个字符串或者是一个字符表达式
stringObject.replace(regexp/substr, replacement)
var str = ‘red and blue and red’;
var newstr = str.replace(‘red’, ‘yellow’); //结果为yellow and blue and red
//var newstr = str.replace(/red/, ‘yellow’); 同理
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
最后
今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!
可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。
参数可以是一个字符串或者是一个字符表达式
stringObject.replace(regexp/substr, replacement)
var str = ‘red and blue and red’;
var newstr = str.replace(‘red’, ‘yellow’); //结果为yellow and blue and red
//var newstr = str.replace(/red/, ‘yellow’); 同理
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-ky28v5wM-1710796712296)]
[外链图片转存中…(img-MkghudpN-1710796712297)]
[外链图片转存中…(img-XCEyNhAY-1710796712297)]
[外链图片转存中…(img-U7EevHWs-1710796712297)]由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-al224rBO-1710796712298)]最后
今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!
可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-