您的位置:首页 > Web前端 > JavaScript

js加强:js引擎,变量作用域,arguments对象,特殊函数,闭包

2017-01-21 09:48 801 查看
 讲师:觉月

1  JS回顾

1.核心浏览器  

  5个: IE Chrome  FireFox  Safari Opera

 

2.脚本语言概念

  字符串,不用翻译,嵌入在其他的软件中运行的语言

 例:  Excel:VBA , Flash:ActionScript  ,JavaScript:

 

3.ECMAScript与JavaScript的关系?

  标准,标准的实现

 

4.JavaScript与Java有无区别,区别大不大? 
面试题

   1.基于对象的一门语言,java:面向对象类/继承/多态  

   2.运行环境:

   3.强弱类型:

 

5 JS能做什么?

     1.表单验证.

     2.获取DOM节点进行操作:属性,样式CRUD

     3.Ajax

     4.网页游戏

     5.网页特效

 

6.技术回顾

   1.获取节点,操作节点属性和样式

   2.为节点绑定各种事件   
内容,样式,行为分离

   3.CRUD以及遍历节点

DOM节点操作
1.获取一个节点,操作这个DOM节点的

1.文本内容,2样式名字 3.节点的标签名字 4.样式操作

        var  dm=document.getElementById(“aa”);

    alert(dm.innerHTML);

    alert(dm.className); //为什么是className

    alert(dm.tagName);

2.对节点进行CRUD.

  Node节点的属性

     childNodes  返回节点到子节点的节点列表

     firstNode 返回节点的首个子节点。

     lastNode 返回节点的最后一个子节点

     nextSibling返回节点之后紧跟的同级节点

     nodeName 返回节点的名称,根据其类型

     nodeValue 设置或返回节点的值,根据其类型

     parentNode 属性可返回某节点的父节点。

     previousSibling 属性可返回某节点之前紧跟的节点(处于同一树层级)

     textContent 属性可设置或返回节点及其后代的文本内容。

  Node对象的方法

    appendChild(new) 方法可向节点的子节点列表的末尾添加新的子节点。

    hasAttributes() 方法会在某节点用于任何属性时返回 true,否则返回 false

    hasChildNodes()方法可在某节点用于任何子节点时返回 true,否则返回 false

insertBefore(new,ref) 方法可在已有的子节点前插入一个新的子节点。

removeChild(node) 方法可从子节点列表中删除某个节点。

replaceChild(new,old) 方法可将某个子节点替换为另一个

 

3. innerHTML和innerText的区别  $(“#rr”).html();  $(“#rr”).text(); 
  <div id=”rr”> <p>DDD</p> </div>

   innerHTML

 也就是从对象的起始位置到终止位置的全部内容,包括Html标签。

   innerTEXT

     从起始位置到终止位置的内容, 但它去除Html标签

 

 

   4.Ajax的实现

     流程: 
创建核心对象绑定函数 打开连接 
发送数据 处理回调函数

      核心对象的5种状态:每种状态的含义

 

8.专业的Web前端的方向有哪些技术呢?

    1.Html,css    2.ECMAScript

    3.BOM       4.DOM

    5. ajax  xml  json  

    6. Jquery bootstrap argular.js   Ext

 

2   JS引擎以及JS工作原理介绍

 

1.JS中使用不存在的变量和使用存在未被赋值的变量

<script>

         alert("ZZZZ");

         //alert(name);

         /*

         function fn(name, age){

                  this.name = name;

                  this.age = age;

         }

         window.fn("zhangsan",19);*/

        

         //最外层的变量和函数是属于window对象的属性  调用window对象的属性不需要加window.

        

         //window.alert("DDDDD");

         //window.fn("DDDDD");

</script>

 

<script>

//alert(v); error v is not defined

var i;

alert(i); //undefined

alert("ZZZZZZZ");

</script>

 

2.JS引擎概念:

简单地说,JavaScript解析引擎就是能够“读懂”JavaScript代码,并准确地给出代

码运行结果的一段程序。比方说,当你写了 var a = 1 + 1; 这样一段代码,JavaScript

引擎做的事情就是看懂(解析)你这段代码,并且将a的值变为2.


 

3.JS引擎工作内容

  1.识别JS代码

  2.创建大量的各种对象

  3.优先将最外层的变量定义语句和函数定义语句得到执行

  正是由于各家的JS引擎不一致,导致JS程序有各种兼容性问题

 

识别HTML标签: html引擎

Css:CSS引擎

Js:js引擎

 

3   变量的作用域

作用域:变量和函数能够存在的范围

 

1.区分基本变量和引用变量

 

<script>

//var i="DDD";

//alert(typeof i);  //string    

var o=new Object();

function Stu(){}

var s=new Stu();

 

//alert(typeof o); //object

//alert(typeof s); //object

 

 

//测试引用类型是由那个类来创造的

//alert(o instanceof Object);  //true

//alert(o instanceof Stu);    //false

//alert(s instanceof Object); //true

//alert(s instanceof Stu);  //true

 

var oo=new Object();

//测试2个引用是否指向同一个区域

alert(o==oo);      //false

</script>



 

2.测试基本类型和引用类型的方法

  基本类型: number stringboolean null undefined

  引用类型: Array Function
自定义类型Object

  var i=”abc”; 

   typeof instanceof    o1==o2

 

3.变量的作用域

   1.JS中只有全局作用域和函数级别的作用域,没有块级作用域

 JS中有全局变量和局部(函数内的)变量

    2.js中全局变量的作用域为全局作用域和局部作用域

3.js中的局部变量的作用域为函数级别

 

全局变量作用域

<script>

alert(v); //undefined

var v=10;

alert(v); //10

function fn(){

         alert(v);

}

fn(); //10

</script>

</head>

局部变量作用域

<script>

//alert(v);  error

var i=23;

function fn(){

         alert(v);  //undefined

         var v=10;

         alert(v); //10

}

fn();

//alert(v); //error

</script>

 

 

4.js全局变量和局部变量重名的时候,
局部变量会覆盖掉全局变量,在函数内访问

     局部变量永远访问到的都是局部的,无论在局部变量定义之前还是定义之后在

     函数内定义变量如果不用var修饰,那么会将这个变量自动提升为全局的,但是

     必须让这个函数得到执行.

     强烈推荐:定义变量都要加 var;

 

 

 4.全局变量和最外层函数都是属于Window对象的属性而存在的,

   alert(); 我们在写JS代码的时候,调用window的属性和方法时,

   “window.”是可以省略的 

 5.体会基于对象,什么是基于对象?

   var i=23;

   window.document.getElementById();

   几乎我们在JS的大部分操作都可以找到一个最终的宿主.

   我们写任何一条JS语句,这条语句都是属于某个对象的.

5.arguments对象 arguments:参数

 

 1.arguments是函数的内部对象,离开函数arguments对象一无是处

 2.arguments.length代表当前正在执行的函数的参数个数

  3.我们可以通过arguments[下标]的形式获得函数的每一个参数

<script>

//alert(arguments); //error

//alert("ZZZZZ");

function fn(a,b,c,d){

         //alert(arguments);  //arguments只能在函数中使用

         //alert(arguments.length); //当前函数接受的参数的个数

          alert(arguments[0]); //通过aruments[小标] 的形式来 获得当前的每一个参数

          alert(arguments[1]);

          alert(arguments[2]);

          alert(arguments[3]); 

}

fn(1,2,3,4);

</script>

 

  4.我们可以通过arguments对象来模拟实现js函数的重载

例1

<script>

//alert(10+undefined); //NaN

function sum(a,b){

         alert("111111");//没有执行这里

         return a+b;

}

function sum(a,b,c){

         alert("2222222");

         return a+b+c;

}

alert(sum(1,2)); //NaN

alert(sum(1,2,3)); //6

</script>

模拟重载

<script>

function sum(){

         var s=0;

         if(arguments.length>0){

                  for(var i=0;i<arguments.length;i++){

                          s+=arguments[i];

                  }

         }

         return s;

}

alert(sum(1,2));

alert(sum(1,2,3));

</script>

模拟重载(理解jquery)

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

<script>

function $(id){

         var dm=document.getElementById(id);

         dm.html=function(args){

                  if(args!=null){

                          dm.innerHTML=args;

                  }else{

                          return dm.innerHTML;

                  }

         }

         return dm;

}

function fn(){

         alert($("dv").html());

         $("dv").html("ZZZZZZZZZZ");

}

</script>

</head>

<body>

<div id="dv">AAAA</div>

<button onclick="fn()">阿牛</button>

</body>

</html>

 

  5.我们可以通过arguments.callee来优化函数的递归调用

 

<script>

         function fn(){

                  var i;

                  i=-23;

                  i=2323;

                  alert(arguments.callee);//指向了arguments参数所在的函数

         }

         fn();

</script>

优化递归(解耦)

<script>

function jm(v){

         if(v==1){return 1;}

         else{

                  return v*arguments.callee(v-1);

         }      

}

alert(jm(6));

</script>

 

 

4   几种特殊的函数

  1. 常规函数

1.最常规的方式
function fn1(){
    alert("11111111");
}
 
2. 将函数最为一个字符串赋值给一个变量,通过 "变量名()"形式来调用函数
var fn2=function(){
    alert("22222222");
}
 
3.将函数当做一个对象来创建,第一个和第二个字符串代表要传递给这个函数的参数,第3个字符串代表函数体中的语句

var fn3=new Function("a","b","alert('33333333'+(a+b))");

 

2.函数也是对象   $.post(“”,{},function(){});

3.函数可以作为参数传递

    1.将函数当做参数传递给另外的函数

    2.将函数作为参数返回,区分返回函数的执行结果  return fn(); // return fn;

<script>

/*     

var d=new Date();

 

function fn(c){

 var str=new String("abc");

 return str;

}

fn(d);*/

 

function fn(){

         alert("fn.....");

}

 

//alert(fn()); //js中的函数如果没有明确说明返回什么值,默认undefined

 

function fm(ff){

         alert("fm.....");

         ff();

        

         function fc(){

                  alert("fc......");

         }

        

         //return fc;

         return fc(); //理解返回的是整个函数,还是函数执行完毕的结果

}

var d=fm(fn);

//d();

alert(d);

</script>

 

  4.函数的call调用和apply调用

window.fn();  fn.call(s,1,2,3);  fn.apply(s,[1,2,3]);

 function fn(){

 }

<script>

         window.age=18;

         function fn(a,b){

                  alert("DDDD"+this.age+" "+a+"  "+b);

                  var zz=23;

         }

//window.fn();

//fn.call();

//fn.apply();

        

//       fn.call();

         //window.fn.call(); //可以通过fn.call()的形式来调用一个函数

         var s={"age":29,"name":"mary"};

         fn.call(s,10,20); //通过call的形式来调用函数,可以向函数中传递一个引用对象,它的意义可以将函数内部的this改变

</script>

apply()

<script>

         window.age=18;

         alert(window.dd);

         function fn(a,b){

                  alert("DDDD"+this.age+" "+a+"  "+b);

                  var zz=23;

         }

         //window.fn();

         //window.fn.call(); //可以通过fn.call()的形式来调用一个函数

        

         var s={"age":29,"name":"mary"};

        

         fn.apply(s,[10,20]); //通过apply调用函数,为函数传递参数的时候必须以数组的形式来传递

</script>

 

 

    

  5.什么是顶级变量污染?

     自己实现JS代码的时候,理想状态,只有1个或者没有全局变量,因为

     这样一可以减少顶级变量污染,二可以提升性能.

    

  6.分析代码执行过程,来了解JS运行过程

 function Stu(){  }

好软件: 满足用户需求的基础上运行速度快,占用资源少(内存的研究)

 

  7.特殊函数

回调函数:

<script>

//是机器人厂家写好地 函数       

function JiQi(yl,cm,fn){

         var flag=false;

         if(yl=='五花肉'){

                  if(cm=='回锅肉'){

                          alert("添水。。。放菜。。。");

                          flag=true;

                          fn(flag);

                  }

         }

}

 

 

JiQi("五花肉","回锅肉",function(dt){

         if(dt){

                  alert("开吃....");

         }

});

//回调函数 : 实现JS代码的时候,调用某些函数的时候,可以向这些函数传递另外的函数,被传递的函数就是回调函数

//场合:先调用别人的函数,JS代码,之后调用"我的"代码,"我的"代码放在函数中.

 

</script>

 

匿名函数

自调函数

<script>

//var fn=function(){alert("ZZZZZ");} //没有名字的函数:匿名函数

 

2+(34+4)

(function(a,b){

         alert("fn...."+a+" "+b);

})(3,3);

 

//匿名+自调: 定义完一个函数之后立马调用. 只调用一次

//适用场合:一次性的初始化工作

//格式 :   ()()  第1对()放的是函数的定义   第2对()代表对函数的调用 

</script>

 

内部(私有)函数 function(){var i=23; function aa(){} }

成员函数:

静态函数: 

<script>

 

function ff(){

         var i=23;

}      

ff();

 

function Stu()

{

         //私有函数/内部函数

         function fn(){}  //<===>var fn=new Function();

        

         var i=23;

        

         //成员函数

         this.fm=function(){alert("fm....");}

}

//fc函数只能通过Stu来调用,认为fc就是属于静态函数

Stu.fc=function(){alert("fc....");}

 

var s1=new Stu();

var s2=new Stu();

//s1.fm();

//s2.fm();

Stu.fc();

</script>

 

 

 

5   闭包

要理解闭包,首先必须理解Javascript特殊的变量作用域。

1. 变量的作用域链

<script>
var v=10000;
function fn1(){

function fn2(){

function fn3(){

alert(v);
}
fn3();
}
fn2();
}
fn1();
</script>

总结:当在函数fn3中使用/访问变量i的时候,

1.先在函数fn3内寻找有没有变量i. 如果有拿过来使用或者访问即可

2.如果没有,去fn3所在的函数fn2内去寻找有没有一个变量I, 如果有拿过来使用或者访问即可

3. 如果fn2内没有I,去fn2所在的函数fn1内去寻找有没有变量i. 如果有拿过来使用

4. 如果fn1内没有I,全局范围内寻找有没有变量i. 如果有拿过来使用

5. 如果全局范围内也没有i.报错.

   fn3寻找变量i的过程,逐层向外寻找的过程,就形成了一个链条.这个就是变量的作用域链

 

2. 闭包

概念理解:

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

用途:

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

<script type="text/javascript">
         /*
          *  我要获取函数fn2中的变量i的值
          */
function fn1(){
         function fn2(){
                  var i=20;
                  return i;
         }
         //fn2();执行fn2函数,虽然fn2函数返回了一个值i,但是没有赋予给任何变量
         //fn1函数在此处默认有一句话return undefined;
         return fn2; //此处最为关键,将fn2这个函数整体返回
}      
function fn(){
         var d=fn1();//得到的是一个函数fn2
         var dm=d();//通过"d()"的形式来调用函数fn2,调用之后,返回了fn2函数的值i
         alert(dm);
}
</script>

 

3. 循环中的闭包

  

<script>

function fn(){

         //var obj={}; //var obj=new Object();

         var arr=[]; //var arr=new Array();

         for(var i=0;i<3;i++){

                  arr[i] = function(){alert(i);}

         }

         return arr;

}

var ar=fn();

ar[0](); //3

ar[1](); //3

ar[2](); //3

</script>

 

     

 闭包使用注意

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

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐