一、 闭包、this、作用域、正则验证
1.1 闭包的概念
在函数内部声明的函数,可以访问函数的局部变量。闭包就是能够读取其他函数内部变量的函数。
有权访问另一个函数作用域中的变量的函数。就是拿到本不该属于他的东西。
作用:闭包可以用在许多地方。它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,延长生命周期。
1.1.3 闭包的好处和问题
好处:
1.希望一个变量长期驻扎内存
2.避免全局变量的污染
3.私有成员的存在
问题:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
1、占内存 (不能及时释放内存)
2、对捕获的变量是引用,不是复制
3、父函数每调用一次,会产生不同的闭包
1.1.4 闭包实现
实现步骤:
1、把一个个功能封装在不同的函数中
2、把所有功能函数封装在一个自运行函数中,同时自运行函数要赋给一个变量,方便外部通过该变量名访问内部的功能。
3、自运行函数末尾一定有 return语句,把各个功能函数以返回值的形式返回给json格式的数据。
注意: 这样内部的函数就可在外部以对象方法的形式调用。
var circle = (function(){
var r = 3; //私有成员,不能被外部访问,但可以被内部子函数调用
function c(){
var result=2*Math.PI*r;
alert("周长是:"+result);
}
function s(){
var result=Math.PI*r*r;
alert("面积是:"+result);
}
return {
zc:c, //json结构
mj:s
}
})();
circle.zc(); //2
circle.mj(); //3
1.2 垃圾回收机制
1.2.1 标记清除
标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量的标记和被环境中的变量引用的变量的标记,此后,如果变量再被标记则表示此变量准备被删除。
2008年为止,IE,Firefox,opera,chrome,Safari的javascript****都用使用了该方式;
1.2.2 引用计数
引用计数:跟踪记录每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这个值的引用次数就是1,如果这个值再被赋值给另一个变量,则引用次数加1。相反,如果一个变量脱离了该值的引用,则该值引用次数减1,当次数为0时,就会等待垃圾收集器的回收
注意:除了一些极老版本的IE,目前市面上的JS引擎基本采用标记清除的方式实现垃圾回收。
1.1.1 变量作用域
一段代码在程序中起作用的范围-就是变量作用域。
变量作用域:局部变量和全局变量
局部变量:在函数内部使用var声明的变量为局部变量,只能在函数内使用
全部变量: 在函数外声明的变量为全局变量或者在函数内部不使用var声明 的变量也是全局变量,作用范围是当前网页,
JS不存在块级作用域,在写for 时注意变量的使用。
在函数外不能读取局部变量
二、作用域链
概念:在一个函数中嵌套多个函数,当函数访问变量时,就形成了作用域链。
查找顺序:从当前函数开始查找,如果没有找到,向上一级函数开始查找,直到找到为止,如果一直没有找到,则说明该变量未定义。
在函数内部嵌套多个函数,当内部的函数访问某个变量时,从当前函数开始查找,如果没有找到,向上一级函数开始查找,直到找到为止,如果一直没有找到,则说明该变量未定义,这样类似链条,我们叫作用域链。
简言之 ----- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问就是作用域链。
三、 this 指向
事件处理程序里面this的指向 ----Window
如果有对象调用事件 – this 指向 当前对象。
return false 的作用是什么?
1、阻止默认事件
2、阻止冒泡
3、退出函数
四、 正则
2.1 正则的语法、概念
什么是正则表达式:是对字符串操作的一种逻辑公式,事先定义好的一些特定的字符、及这些特定字符的组合,组成一个“规则字符串”,这些特定字符串是对字符串一种过滤逻辑。
正则表达式的作用:
给定一个正则表达式和一个字符串,我们可以做到以下目的
1.给定的字符串是否符合正则表达式的过滤逻辑
2.可以通过正则表达式,从字符串获取我们想要的特定的部分
正则表达式的特点:
1.灵活性,逻辑性和功能性非常强
2.可以迅速的用极简单的方式达到对字符串的复杂的控制
创建正则表达式方法
1.构造函数方式 var reg=new RegExp(“表达式”,“附加的参数”)
2.普通方式 var reg=/表达式/附加参数
正则表达式的使用表示方式
1.test() 语法: reg.test(str) 如果匹配成功,返回true 否则返回false
2.exec() 语法 reg.exec(str) 如果匹配成功,返回的内容,否则返回null
3.replace() 语法 str.replace(reg,“替换成字符”) 返回替换后的内容
正则表达式的 元字符
[0-9] 数字
[a-z] 字母
[A-z] 大小写字母 [a-zA-Z]
[\u4e00-\u9fa5] 中文汉字
[0-9A-z] 数字或字母
[0-9A-z__]数字或字母或下划线
\w 相当于 [A-z0-9_]
\W 和\w 相反,不包含[A-z0-9_]
\d 相当 [0-9]
\D 和 \d 不包含 [0-9]
正则表达式的应用
1.只能是中文 长度为2-7位
/^([\u4e00-\u9fa5]){2,7}$/
2.长度为8到18位的小写大写字母或数字或下划线
/^[a-zA-Z0-9_]{8,18}$/
3.正确的邮箱格式
/^[A-Za-z0-9\u4e00-\u9fa5_]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
4.正确的手机号
/^1(3|4|5|7|8)\d{9}$/
5.正确的身份证号:
/^\d{15}|\d{17}([0-9]|x)/
/^[1-9][0-9]{16}[0-9x]$/
6.正确的qq号
/[1-9][0-9]{4,}/
7.正确的电话号码格式
量词
+ 至少包含一个前导字符
? 包含0个或1个前导字符
* 包含0个或多个前导字符
. 匹配任意字符 有几个点,就匹配几个
{x} 匹配包含x个前导字符
{x,y} 匹配包含x到y个前导字符
{x,} 匹配至少包含x个前导字符
$匹配字符串的行尾,$
^ 字符串开头
五、 继承
5.1 继承的概念
什么叫继承:
继承是指一个对象直接使用另外一个对象的属性和方法.继承可以使子类具有父类的属性和方法.而不需要再次编写相同的代码.在子类继承父类时,可以重新定义某些属性,也可以重写某些方法。
为什么要使用继承?
减少无用的多次重复代码;
使用户体验更高、加载更快;
5.2 原型链继承
方法:利用原型链 如下:
function AA(){
this.uname="黄大仙";
}
AA.prototype.usex="先生"
// 以上是AA 的构造函数
function BB(){
}
// BB 构造函数
BB.prototype = new AA(); // 父类(超类)的实例化对像进行 原型链的传递 达到继承
var b1 = new BB();
b1.uname // '黄大仙'
b1.usex //'先生'
1.先声明两个构造函数AA,BB,
2.AA的实例化 赋给BB的原型对象; (继承核心)
3.这样AA所有属性都继承给了BB的原型对象,
4.当BB实例化对象时,实例化对象共享了AA所有属性
原型链继承缺点:
1.通过原型来实现继承时,原型实际上会变成一个类型实例.原先的实例也会变成了原型的属性
2.不能向父类型(超类型)的构造函数中传递函数
5.3 类式继承(借用构造函数)
方法:类式继承 如下:
function AA(uname){
this.name=uname
}
function BB(){
this.sex="女";
AA.call(this,"武大狼"); // 相当于调用AA 构造函数 完成继承
}
var obj=new BB();
alert(obj.name)
this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。
call.(thisOject, arg1 ,arg2 …)
(1).我们单独说说call(),因为apply()和call差不多,只不过apply第二个参数必须传入的是一个数组,而call 第二个参数可以是任意类型。如:
function add (x, y)
{
console.log (x + y);
}
function minus (x, y)
{
console.log (x - y);
}
add.call (minus , 1, 1); //2
这个例子中的意思就是用 add 来替换 minus ,add.call(minus ,1,1) == add(1,1) ,所以运行结果为:console.log (2);
(2).// 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
A.call( B,x,y ):就是把A的函数放到B中运行,x 和 y 是A方法的参数。
用call来实现继承,用this可以继承myfunc1中的所有方法和属性。
function myfunc1(){
this.name = 'Lee';
this.myTxt = function(txt) {
console.log( 'i am',txt );
}
}
function myfunc2(){
myfunc1.call(this);
}
var myfunc3 = new myfunc2();
myfunc3.myTxt('Geing'); // i am Geing
console.log (myfunc3.name); // Lee
类式继承优点:可以给父类的构造函数传参
**类式继承缺点:*不能继承父类的原型。
5.4 组合继承
通过原型链继承,同时也借用构造函数方式继承叫组合继承
方法如下:
function AA(){
this.name="如花姑娘"
}
AA.prototype.say = function(){
alert(this.name);
}
function CC(){
AA.call(this) ; // 类式继承
}
CC.prototype=new AA(); // 原型链继承
var cs = new CC( );
alert(cs.name)
优点:使用原型链对原型属性和方法的继承,而通过构造函数来实现对实例属性继承,通过原型方法实现的函
数的利用,又能保证每个实例都有自己的属性。
缺点:无论在什么情况,都会调用两次超类型的构造函数,一次在创建子类型原型的时候,另一次是在子类型构
造函数内部。
我们就把js里面的常用继承讲完了,总结一下3种继承
- 原型链继承,会共享引用属性
- 构造函数继承,会独享所有属性,包括引用属性(重点是函数)
- 组合继承,利用原型链继承要共享的属性,利用构造函数继承要独享的方法,实现相对完美的继承
总结:
以上就是初学者必须知道的JavaScript认识(三),原创不易,期待您的点赞关注与转发评论😜😜😜