阅读 100

初学者必须知道的JavaScript认识(三)

一、  闭包、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年为止,IEFirefoxoperachromeSafarijavascript****都用使用了该方式;

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种继承

  1. 原型链继承,会共享引用属性

  2. 构造函数继承,会独享所有属性,包括引用属性(重点是函数)

  3. 组合继承,利用原型链继承要共享的属性,利用构造函数继承要独享的方法,实现相对完美的继承


作者:张清悠
链接:https://juejin.cn/post/7016272406037659679


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐