前端技术的发展变化太快了,各种各样的框架。再变也离不开js。所以,在此把js的高级语法总结一遍。    js解析和执行包括:全局和函数

一:全局预处理

<script type="text/javascript">
var a=1;
function xx(){
alert(a);
}
</script>

  这段代码会正常输出a=1;

<script type="text/javascript">
var a=1;
function xx(){
alert(a);
var a=5;
}
</script>

输出 undefined   为什么呢?  不报错  输出undefined 。   这就是js的解析执行过程

js执行过程分为:预处理的阶段和执行阶段  

预处理阶段:

一:创建一个词法环境  LexicalEnvironment==window

二:扫描js代码:

1.用声明的方法创建的函数

2.用var   定义的变量

预处理js处理命名冲突:

先扫描函数声明后扫描变量(var声明)

处理函数声明有冲突会覆盖

处理变量声明有冲突,会忽略

下面为例子:

 <script type="text/javascript">
alert(a); //undefined
alert(b); //报错
alert(f); //字符串的表达式
alert(g); //undefined var a=5;
b=6;
alert(b);
function f(){ console.log('f');
} //表达式创建的函数
var g=function(){
console.log('g'); }
alert(g);
</script> js分为两个阶段:
一:预处理阶段 1.var 定义的变量 2.声明的方式创建的函数 window
{
f:指向函数
a:undefined
g:undefined (表达式创建的函数可以当成变量) } 二:执行时 没有定义var 就一次性赋值
window
{
f:输出函数的值
a:5 变量的定义
b: 6 函数赋值
g:指向函数 }

  作用域:

<script type="text/javascript">
alert(a); //undefined
alert(b); //undefined
alert(c); //报错
alert(d); //报错 var a=1;
if (false) {
var b=2;
}else{
c=3;
} function f(){
var d=4;
} for (var i = 0; i <3; i++) { }
alert(i); //输出3 说明:js是没有块作用域的
js是不垮作用域的

  函数作用域:

function f(){
var x
function g(){
//函数 g()是不能访问 var x的
}
}

  动态作用域 :   只有在用行时确定

function f(){
alert(x);
} function f1(){
var x=5;
f();
} function f2(){
var x=6 ;
f();
}
f1(); //报错 (等于window 没有全局变量) 说明js 没有动态作用域

  静态作用域  别称:词法作用域 (lexical)   闭包

词法作用域的特点:
一:在js解析器读取创建函数的时候
1.给函数 f 添加一个成员 【【scopel】】 ==创建 函数 f 时的词法环境(lexicalEnv)==window
2.调用 f(); 真正开始执行的时候 创建自己的词法环境 (lexical)==函数本身 f.[[scope]]==window
二:在词法解析解析阶段(在声明的阶段) 确定了相关的作用域

var x=100;
function f(){
alert(x);
} function f1(){
var x=5;
f();
} function f2(){
var x=6 ;
f();
}
f1(); //输出100

  作用域链条:

 function f(){   // 解析  f的 scope==window
f 调用时创建自己的词法 (lexical {x=100})-->f.[[scope]]
var x=100;
function g(){ //创建 g时 g.[[scope]]==f.(lexical)
// g 运行时创建自己的(lexical)-->指向了 g[[score]] }
g();
}

   形成的链条:

g.lexical-->g。[[scope]]  -->f.lexical  --->f.[[scope]] --->window

js创建函数的方式:

1.声明的方式
function f(){ }
2.匿名函数
var f=function(){ }
3.匿名函数
var f=function x(Aargument){ }
4. var f=new Function(“参数”,“alert(xx)函数体”) function f(){ //给f scope==window 预处理阶段 把x和g 加进去
var x=100;
var g=function(){ //g.score==f.lexical
alert(x);
}
g();
}
f(); //输出100 function f(){
var x=100;
//g.[[scope]]==window
var g= new Function(“”,“alert(x)”);
g(); //报错 x没有定义
}
f(); </script>

  

作用域的本质:
当在函数中找到一个变量的时候,首先,会在这个函数本身的词法环境中去找,找到结束--->找不到,去父函数的词法环境中去找--->window 中途找到退出

具体的用法:(作用域就是一个信息隐藏)

全局变量越来越多时,会导致冲突。

匿名的立即调用函数的写法:
(function(){
var a=5;
var b=6;
function f(){
alert(a); }
window.f=f; //技巧:在外面能访问到 定义window })();
f(); //输出5
这样就只对外面提供了一个f函数,减少了命名的冲突

  闭包:

定义:是词法闭包的简称,引用了自由变量的函数,这个被引用的自由变量将和这个函数一同存在。即使离开了他的创建环境也不例外。(闭包就是一个对象,里面包含的一个函数,函数中有被他补货的变量)

本质:js支持作用链和函数的嵌套函数

自由变量指父函数的自由变量(a,b)

闭包是什么时候创建的呢:

1.给f2创建一个[[scope]],===父函数f1的词法环境

2.扫描f2的代码,保留f1的词法环境

闭包函数的写法:

如何查看(在浏览器中):

代码:

<script type="text/javascript">

function f1(){   //父函数
var a=10;
var b=20;
function f2(){ //子函数
coonsole.log(a);
}
f2();
}
f1(); //即使离开了他的创建环境也不例外。
function f1(){
var a=10;
var b=20;
return function f2(){
coonsole.log(a);
}
}
var result=f1();
result();
</script>

  不调用父元素的属性是不会产生闭包的。

代码:

function f1(){
var m=10;
function f2(){ coonsole.log("fss");
}
f2();
}
f1();

  不会看到任何结果:

调用父的父元素:(是可以产生闭包的)

function f1(){
var m=10;
function f2(){
var n=20; function f3(){
coonsole.log(m);
}
f3();
}
f2();
}

  效果:

使用闭包的优势:

1.减少全局变量

 function add(){
var a=0;
return function(){
a++;
alert(a);
}
}
var result=f();
resul ();
resul ();

2.减少传递给函数的参数数量

 //减少参数
function add(base,max){ }
//构建一个计算工厂的函数
function calFactory(base){
return function(max){
var total=0;
for (var i = 1; i <=max; i++) {
total+=i;
}
return total+base;
}
} var adder=calFactory(2);
alert(adder(3)); //输出8;
alert(4); //输出12 var adder2=calFactory(1);
alert (adder2(3)); //输出7 function calFactory(base){
return function (max){
var total=0;
for (var i = 1 ; i <=max; i++) {
total+=i;
}
return total+base; }
}

3.封装

//立即调用的函数
(function(){
var m=0;
function getM(){
return m;
}
funciton setM(){
m=val;
}
window.g=getM;
window.f3()=setM;
})(); f(12);
alert(g()); //输出12

  

闭包的注意点:

一:对捕获的变量只是个引用,不是复制

function f(){
var num=1; function g(){
alert(num);
}
num++;
g();
}
f(); //输出2

  

//分析:
1.f调用生成一个f 的词法环境 le==g的[[scope]] 产生闭包 g函数没有真正的运行 num++;
2.f的词法环境是一个对象 (num就是一个成员) num的值就是f函数的词法环境
3.g的[[scope]]==f 的 le==num
所以就是对象的引用

二:父函数每调用一次,会产生不同的闭包

 function f(){
var num=1;
return function(){
num++;
alert(num);
}
}
var result1=f();
result1();//2
result1();//3 var result2=f();
result2();//2
result2(); //3 分析:
1.调用两次不同的 f() 就创建了不同的词法环境
所以:父函数没调用一次就会产生不同的闭包

  三:循环中的问题

<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div> <script type="text/javascript">
for (var i = 1;i <=3; i++) {
var ele=document.getElementById(i);
ele.onclick=function(){
alert(i);
}
}
//点击一直输出4 //解决方案 闭包 用匿名函数
for (var i = 1;i <=3; i++) {
var ele=document.getElementById(i);
ele.onclick= (function(id){
return function(){
alert(id);
}
})(i);
}

对象的种类:

1. undefined

2.null

3.string

4.number

5.boolean 

对象的类型:

1.js内置的

2.宿主环境(window)

3.自己创建

对象的创建:

1.对象自变量的创建

<script type="text/javascript">
var p={
name:“sunliyuan”,
work:function(){
console.log("working...");
}, _age:18,
get age(){ return this._aga; }, set age(val){
if(val<0||val>150){
throw new Error("invalid value");
}else{
this._aga=val;
}
},
address:
}; console.log(p.name); </script>

  

又一访问种方式:

括号的访问:

级联访问实例:

通过Object对象:

自己给自己加上属性:

另一种加法:

 

还是100(不可修改)

//get,set,writable,enuerable,configurable,value
Object.definePropertis(p,{
salary:{
value:1000,
writable:false
},
gender:{
value:true
},
height:{
get:function(){
return 180
},
set:function(val){
console.log(val);
}
} });

  输出的内容:

JavaScrit全面总结的更多相关文章

  1. javascrit原生实现jquery的append()函数

    /** * javascrit原生实现jquery的append()函数 * @param parent * @param text */ function append(parent, text) ...

  2. javascrit开发的基本代码结构的

    今天看到群里一个demo,简单看了一下. 然后自己就写了一个通用的javascrit开发的基本代码结构的js文件. 代码例如以下: (function($,win){ //定义全局变量对象 var o ...

  3. 在javascrit中怎样来刷新页面

    a页面里iframe了个b页面,我想实现在b页面里一个按钮,一按就刷新a页面,也就是父页面,不是只刷新iframe里面的b页面 哦~ 请问b页面里的<input type="butto ...

  4. javascrit字符串截取

    昨天遇见一个问题就是一个地址后面加参数第一次是需要添加参数,以后每次点击按钮的时候是替换如果不进行处理的话如果页面不刷新,地址会不断的添加越来越长,所以

  5. Javascrit 总结

    1. 数组三种表达方法 第一种 var arr = new Array(1,2,3); document.writeln(arr+"<br/>"); 第二种 var a ...

  6. javascrit中“字符串为什么可以调用成员”

    <script> var title = "this is title"; console.log(title.substr(0,5));   //字符串为什么可以调用 ...

  7. Javascript单例模式概念与实例

    前言 和其他编程语言一样,Javascript同样拥有着很多种设计模式,比如单例模式.代理模式.观察者模式等,熟练运用Javascript的设计模式可以使我们的代码逻辑更加清晰,并且更加易于维护和重构 ...

  8. JavaScript中‘this’关键词的优雅解释

    本文转载自:众成翻译 译者:MinweiShen 链接:http://www.zcfy.cc/article/901 原文:https://rainsoft.io/gentle-explanation ...

  9. Js函数的概念、作用、创建、调用!

    一.函数是用来帮助我们封装.调用代码的最方便的工具! 二.函数的创建方法有三种: 三.函数的创建方式有3种,调用方式也不是单一的,调用方式有4种!      1.作为一个函数去调用 函数名+();(函 ...

随机推荐

  1. java序列化深拷贝【转】

    java深拷贝 序列化和反序列化合成在一起的方法CloneUtils import java.io.ByteArrayInputStream; import java.io.ByteArrayOutp ...

  2. Linq 中的 in 与 not in 的使用

    接 触 LINQ 也有很长的一段时间了,有些在 SQL 语句中用的很顺手的东西在 Linq 中却不知道如何实现了,最近遇到了一个问题,在 LINQ 的 Where 条件式中要如何使用 IN 与 NOT ...

  3. Java SE之字符串常量池

    Reference Document: 什么是字符串常量池?   http://www.importnew.com/10756.html[Recommend] Java常量池理解与总结   http: ...

  4. django(二)中间件与面向切面编程

    一.中间件概念 django 自带函数可以在几个环节调节收到请求.处理请求.处理异常.以及发送请求. 看这里给的链接好了,这是一个大佬的讲django中间件的博客,非常清楚:https://www.c ...

  5. shiroWeb项目-认证及MD5认证信息在页面显示(十)

    realm设置完整认证信息 // realm的认证方法,从数据库查询用户信息 @Override protected AuthenticationInfo doGetAuthenticationInf ...

  6. Django 查询集简述

    通过模型中的管理器构造一个查询集(QuerySet),来从数据库中获取对象.查询集表示从数据库中取出来的对象的集合.它可以含有零个.一个或者多个过滤器.过滤器基于所给的参数限制查询的结果. 从SQL ...

  7. DMA内存申请--dma_alloc_coherent 及 寄存器与内存【转】

    转自:https://blog.csdn.net/ic_soc_arm_robin/article/details/8203933 在项目驱动过程中会经常用到dma传输数据,而dma需要的内存有自己的 ...

  8. mysql系列八、mysql数据库优化、慢查询优化、执行计划分析

    mysql的性能优化无法一蹴而就,必须一步一步慢慢来,从各个方面进行优化,最终性能就会有大的提升. 一.介绍 对mysql优化是一个综合性的技术,主要包括 表的设计合理化(符合3NF) 添加适当索引( ...

  9. weblogic实时监控开发

    参考api文档 https://docs.oracle.com/cd/E13222_01/wls/docs90/wlsmbeanref/core/index.html https://docs.ora ...

  10. 安装java时,配置环境变量classpath的作用

    想必大家在安装javaSE或其它版本时会注意到,在配置环境变量path之后,还需要新建一个名为CLASSPATH,变量值设为 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt. ...