`

悟透JS

 
阅读更多

1, 在js中 “123” == 123,“0123” == 0123,”123” === 123,”123” !== 123,”123” != 123 有什么不同?
“123” == 123的值为true,”0123” == 0123的值为false,因为js中将“0”开头的整数常量当八进制数处理。如undefined==null返回true。
“123” == 123的值为true,”123” === 123的值为false,因为js中“===”表示全等,也就是数据值与数据类型都必须相等才是true。
”123” !== 123的值为true,”123” != 123的值为false,因为“!==”表示不全等,“!=”表示值不等。不全等即值或类型不相等,不全等相当于 ”123” !== 123 || typeof(“123”) != typeof(123)。全不等即值和类型都不相等,全不等相当于”123” !== 123 && typeof(“123”) != typeof(123)。

2, Underfinedhe和null
Undefined:代表一切未知事物,啥都没有,无法想象,代码更无法去处理。
Null:有那么一个概念,但没有东西,无中似有,有中还无,虽不可想象,但代码可以去处理。
Typeof(undefined)返回也是undfined。
Typeof(null)返回object。
Undefined == null 返回true

3, Function 函数
Js中创建function函数类型。定义式和变量式。
<script language="javascript" type="text/javascript">

function myfun(){
alert("hello");
}

myfun();//输出word

function myfun(){
alert("word");
}

myfun();//输出word

</script>

<script language="javascript" type="text/javascript">

var myfun = function (){
alert("hello");
}

myfun();//输出hello

myfun = function (){
alert("word");
}

myfun();//输出word

</script>

Js执行引擎并非一行一行地分析代码和执行程序的,而是一段一段地分析执行的。而且在同一段程序执行中,定义式的语句会被提取出来优先执行,函数定义完之后,才会顺序执行其他语句代码。
上面列子在定义式中,第一次定义的函数myfun被第二次定义的函数myfun覆盖,所以两次执行的是第二次的函数,而在变量式定义函数myfun中,函数看做变量改变过程来执行。

4, 作用域链
代码的时空:相对论告诉我们,时间和空间是不可分割的。我们只有把时间和空间结合起来才能确定一个事件发生的准确坐标。确定一个变量数据的执行时空,就是确定代码变量数据执行的上下文环境,即确定变量数据的作用域。

<script type="text/javascript" language="javascript">

var yourName = "you";
myName = "me";

function changeName(){
alert(myName+"==="+yourName);//me===undefined
var yourName = "your";
myName = "my"
alert(myName+"++++"+yourName);//my++++your
}
alert(myName+"---"+yourName);//me---you

</script>

在js中全局环境就是一个对象,这个对象就是js运行环境的根。对于浏览器中的js来说,这个根对象就是window对象对全局的js来说window对象就相当于当前作用域。
如:var yourName = "you"; //window作用域的一个变量yourName
myName = "me"; //window对象的一个属性myName
对于全局的js来说,加不加var都一样,不过在子作用域里就不一样了。
Var定义的是该作用域上的一个变量。而没有var标识的变量则需要在作用域链上查找变量,如果从子作用域到根定义中没有查找到该变量,则该变量为该作用域上的变量。反之既然。
在js中当代码运行进入一个函数时,js会创建一个新的作用域来作为当前作用域的子作用域。然后将当前作用域切换到这个新的子作用域,开始执行函数的逻辑。而js执行引擎会把此函数内的逻辑代码当做一个单元来分析执行。
Js执行步骤:
第一步:预编译分析,建立可调用的函数变量。将定义式函数直接创建为作用域上的函数变量,并将其值初始化为定义的函数代码逻辑;对于var标识的变量,将其初始化值为undefined。
第二步:解释执行代码,在预编译的环境中执行逻辑代码。当遇到函数名或变量名的使用时,js执行引擎会首先在当前作用域查找函数或变量,如果没有 就到上层作用域查找,以此类推。对于子作用域和父作用域有相同的变量时,根据var来定义作用域。用var定义的变量只对本作用域有效,尽管父作用域中有 同名变量都与本作用域变量无关,退出本函数(本作用域)后,var就失效了。
Js在执行函数时都会产生一个子作用域,退出函数后,这个子作用域就消失了,下次调用该函数是又会有另一个子作用域产生。而在该函数内在调用另外函数时,又会在该函数作用域的基础上产生一个子作用域,从而形成了一个作用域链。作用域链的根是js的根。

5, Caller

function callerA(){
alert("caller is "+callerA.caller);
}

function callerB(){callerA();}

callerA();//caller is null
alert(callerA.caller);//null

callerB();//caller is callerB(){callerA();}

caller是函数自身的一个属性,表示调用当前函数的父函数。如果caller值为null,表示函数没有被调用者或是被全局函数调用。函数的 caller值是动态变化的,函数的caller的初始化值都是null。当调用一个函数数,代码已经运行在函数体内,被调用函数的caller属性就会 设置为当前函数。在退出函数调用时,caller值又恢复为null。

6, 对象和函数的调用
<script type="text/javascript" language="javascript">

var obj = {};//var obj = function(){}
obj.aproperty = "a property";
obj.amethod = function(){alert("a method");}

alert(obj["aproperty"]);
obj["amethod"]();

for(var i in obj){
alert(i+"=="+typeof(obj[i]));
}

</script>

Js中的函数和对象既有对象特性和数组特性。
7, This 自我
<script language="javascript" type="text/javascript">

function whoami(){
alert("i am "+this.name+" of type: "+typeof(this));
}

var whoA = {name: "A"};
whoA.whoami = whoami;

var whoB = {name: "B"};
whoB.whoami = whoami;

whoA.whoami();//this作为whoA  i am A of type: object
whoB.whoami();//this作为whoB  i am B of type: object

whoami.call(whoA);//this作为whoA  i am A of type: object
whoami.call(whoB);//this作为whoB  i am B of type: object

whoB.whoami.call(whoA);//this作为whoA  i am A of type: object
whoA.whoami.call(whoB);//this作为whoB  i am B of type: object

whoami.whoami = whoami;
whoami.name = "I"
whoami.whoami();//this作为whoami  i am I of type: function

</script>
Js中把this看着当前要服务的这个对象。
8, Json对象
<script language="javascript" type="text/javascript">
var json = {
name:"xiaohong",
age:"20",
say:function(){alert(this.name+" hello");}
};

json.say();
</script>
Json是js对象化的一种形式。如果要将一个json字符串转换成js对象,只需要使用eval函数就可以将json字符串转换为一个js对象。

9, js创建对象
js创建对象可以通过new操作符结合函数名来创建对象。
如:
function obj(){};
var o = new obj();//var o = {}; obj.call(o);

在js中先用new操作符创建一个对象,紧接着就将这个对象作为this参数调用后面的函数。

<script language="javascript" type="text/javascript">

function person(name){
this.name = name;
this.say = function(){
alert("I am "+this.name);
}
}

function emp(name, salary){
person.call(this,name);
this.salary = salary;

this.sal = function(){
alert(this.anme+" "+this.salary+"$");
}
}

var p = new person("xiaohong");
var e = new emp("xiaofang",1234);

p.say();//I am xiaohong
e.say();//I am xiaofang

e.sal();//xiaofang 1234$

alert(p.say==e.say);//false

</script>
上面代码表明:emp构造函数将自己的this作为参数调用person的构造函数,就是相当于调用基类的构造函数。
同时通过alert(p.say==e.say);//false,我们也可以看到在emp和person对象中确实各自保存了一份say代码体。
<script type="text/javascript" language="javascript">

function person(name){
this.name = name;
this.say = function(){
alert("I am "+this.name);
}
}

var p1 = new person("xiaohong");
var p2 = new person("xiaofang");

alert(p1.say==p2.say);//false

</script>
同一类的对象各自有一份代码是一种浪费,在js中我们可以同过this来指向同一份代码体。
<script type="text/javascript" language="javascript">

function say(){
alert("I am "+this.name);
}

function person(name){
this.name = name;
this.say = say;
}

var p1 = new person("xiaohong");
var p2 = new person("xiaofang");

alert(p1.say==p2.say);//true

</script>

<script type="text/javascript" language="javascript">

function person(name){
this.name = name;
}

person.prototype.say = function(){
alert("I am "+this.name);
}

var p1 = new person("xiaohong");
var p2 = new person("xiaofang");

alert(p1.say==p2.say);//true

</script>

10, prototype原型,原型链,继承,多态。
在js中所有function类型的对象都有一个prototype属性,prototype是对象的原型。它本身就是一个object类型的对 象,以此我们可以给它添加任意类型的属性和方法。在构造函数的prototype上定义的所有属性和方法,都可以通过其构造的对象直接访问和调用。可以说 prototype给一群同类的对象提供了共享属性和方法。
<script language="javascript" type="text/javascript">

function person(name){
this.name = name;
}

person.prototype.say = function(){
alert("I am "+this.name);
}

function emp(name, salary){
person.call(this,name);//调用基类的构造函数
this.salary = salary;
}

emp.prototype = new person();//建一个基类的对象作为子类原型的原型(原型继承)

emp.prototype.sal = function(){
alert(this.name+" "+this.salary+"$");
}

var p = new person("xiaohong");
var e = new emp("xiaofang",1234);

p.say();//I am xiaohong
e.say();//I am xiaofang

e.sal();//xiaofang 1234$

alert(p.say==e.say);//true

</script>

在js中prototype有寻根问祖的天性,当一个对象那里读取属性或调用方法时,如果该对象自身不存在这样的属性或方法,该对象就会去关联的 prototype对象那里寻找,如果自己关联的prototype那里没有,就会去prototype自己关联的前辈的prototype那里寻找,直 到找到或者寻找到根为此。
对象的属性和方法追溯机制就是通过prototype链来实现的。当用new操作符来构造函数对象时,也会同时将构造函数的prototype对 象指派给新创建的对象,成为该对象的内置的原型对象。内置的原型对象本身也是对象,也有自己关联的原型对象,这样就可以形成原型链。
原型链的最底端,就是Object构造函数prototype属性指向的那一个原型对象。Js中所有的构造函数都是继承于该原型对象。这被称作原型继承。
Js中子对象可以掩盖父对象的属性和方法,即重写了父对象的属性和方法,这种掩盖机制实现了js的多态。

11, 闭包
function a(){
   var i=0;
   function b(){
   alert(++i);
   }
   return b;
  }
  var c = a();
c();

这段代码有两个特点:
  1、函数b嵌套在函数a内部;
  2、函数a返回函数b。
  这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数 a外的变量c引用了函数a内的函数b,就是说:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。
简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。
  在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。
那 么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。
1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
  2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。
以上两点是闭包最基本的应用场景,很多经典案例都源于此。

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

12, 网页运行原理
当打开一个网页时,浏览器会创建一个窗口,这个窗口就是一个window对象,也就是js运行所依附的全局环境对象。为了加载网页文档,当前窗口 将为要打开的网页创建一个document对象,然后将网页加载到这个对象中,网页的内容加载就是在这个过程中一边加载一边呈现出来的。js代码也是伴随 这个过程,一边加载一边执行的。对于外部js可能会分配多个线程去完成加载,但浏览器也会等待需要的js文件加载完成后,最终安正确的顺序来执行js代 码。
进行加载和执行的目的,是为了建立文档对象模型(DOM)的主框架。这个主框架是有当前文档窗口的主线程来处理,并依照样顺序进行的。而网页中可以异步加载其他附属资源,如图片,声音,视频等多媒体数据,是被安排给其他线程去处理的。
浏览器中有多少个线程可以同时加载网页内容?web标准有一个限制,就是对同一个域名最多只允许使用两个连接来读取内容,大多数浏览器都遵循这一 标准。就是说同一个域名的情况下,只有两个线程可以同时加载内容,其他的会处于等待状态。因此,浏览器使用多少个线程在同时加载网页,要看网页内容涉及多 少域名。一个域名两个线程,多了就会堵塞。
当网页主框架加载和执行完毕,浏览器才开始触发window对象或body对象的onload事件。在极少的情况下,网页如果没有body对象, 浏览器会在网页加载完后自动创建一个body对象,并将其设置为document的body属性。Window对象和body对象事件是相通的,就是说, 要么设置window对象的onload事件,要么设置body对象的onload事件,只能有一个起到作用。甚至在ie中两个onload事件就是同一 个东西,设置一个就意味着改变了另一个。
当网页主框架加载执行完成,由此引发的事件也处理完毕,js就暂停执行以等待下一次被触发的时机。如点击,定时刷新等功能被触发,js执行引擎将再次起到,执行相应的js代码。
可以认为js总是被动执行的,并且js绝对是单线程的,不管是窗口主线程加载的js代码,还是外部js代码,以及触发执行的js代码执行,都是在 一个单一的线程中执行的。甚至在一个浏览器进程中,不同窗口对象的相对独立的js代码也是在同一个线程里执行的。也就是说,你打开一个浏览器之后。不管你 在浏览器进程中开启了多少个页面,新打开多少个窗口,里面的所有js代码都是有同一个线程来执行的。即一个浏览器进程中所有的js代码是串行执行的。除非 再打开一个浏览器,创建一个新的浏览器进程。
同时,在网页编写js脚本时,不能太自私编写大量耗时的js脚本。这样可能给在同浏览器其他页面脚本堵塞,从而导致用户体验不好。


13, 文档对象模型
DOM这个术语反映了三个意思:一是“文档”,它表示是一份文档,即网页。二是“对象”,它表示是由一个个可操控的对象构成的。三是“模型”,他表示一个树型结构,一个可编程的模型。
可以这样认为,dom就是一棵树,一棵会开花的树,长在js必经的路旁,为的就是要和js结一段尘缘。只要轻拂一下js,就能让dom翩翩起舞,让dom展现多彩的页面。
Dom对象本质并不是一个纯粹的js对象,他是紧凑的本机数据对象,这些对象大都是以本机二进制的接口模型出现。在ie中dom对象是一个个 com接口对象。而在Firefox中也有自己的接口模型。在浏览器扩展开发的工作中,我们可以直接建立相关dom对象的接口,并通过访问接口的属性和方 法来操作dom对象。
14, Js跨域
浏览器对于网络上的链接会有一些限制,这些限制包括XMLHttpRequest的限制,网络浏览器不会允许脚本去对它本身所在的server之外的server直接链接。
在网络中要实现跨域有两种方法:一是多个不同域名的服务器进行通信,服务器间不受域名的安全限制。二是客户端和多个服务器端进行请求通信,浏览器在这种跨域请求的时候,会受到浏览器的安全限制。
服务器间的跨域访问可以通过服务器代理,web service等来实现跨域访问,不受跨域限制。
客户端直接对服务器端的跨域访问,可以通过动态的js来实现。
一, 动态的script标签实现跨域访问。
本方案利用js脚本动态插入script标签,利用该标签的src属性向服务器端发出请求(可带参数),src属性可指向一个服务器端的处理程序 或脚本。如jsp php action等。服务器段通常返回一段js代码,当js代码返回给客户端的时候,js代码就会被执行,从而导致异步跨域名通信的目的。
通常情况下,服务器端返回的是一个回调函数,该函数的参数已经在服务器端被填充,该回调函数(带着被填充的参数)就会被执行。
客户端:
<script language="javascript">
function callback(arg){
alert("this is "+arg);
}

function getRequest(){
var jsobj = document.createElement("script");
jsobj.src = "http://172.16.23.53:8088/DMS1.0/login/test_test.action?name=aaaaa";
document.body.appendChild(jsobj);
}

</script>
<body>
<input  type="button" value="click" onclick="getRequest();"/>
</body>

服务器端:
<%
PrintWriter out = response.getWriter();
String name = request.getParameter("name");
out.print("callback("+data+")");
%>
二, Iframe实现跨域

客户端:

<script language="javascript">

function client(name){
alert("client method "+name);
}

function envoy(url, method, callback){
var frame = document.createElement("iframe");
frame.style.width = 0;
frame.style.height = 0;
frame.style.visibility = "hidden";

var params = [];
for(var i=3; i<arguments.length; i++){
params.push( arguments[i]);
}

frame.contentWinddow.name = params;

var url = "http://"+url+" #"+method+"/"+callback+"@"+location.host;
frame.contentWindow.location= url;

}

envory(“url”,”service”,”client”,”testparam”);
</script>


服务器端:

<body>
<script language="javascript">

function service(arg){
alert("service method is "+arg);
return “service”;
}

if(!parent || parent == this){
alert(“parent”);
}else{
var command = location.hash.substring(1);
var i = command.indexOf("/");
if(i>0){
var j = command.indexOf("@");
var callback = command.substring(i+1, j);
var domain = command.substring(j+1);
var method = command.substring(0,i);

command = method+"("+window.name+")";
var result = eval(command);

window.name = result;

window.location = "http://"+domain+”#”+callback;
}else{
command = command+"("+window.name+")";
parent.eval(command);
}
}

</script>
</body>

分享到:
评论

相关推荐

    悟透JavaScript(js)

    ### 悟透JavaScript(js):回归数据与代码的本质 #### 一、引言 《悟透JavaScript》这本书由李战(leadzen)撰写,旨在深入浅出地讲解JavaScript的核心概念和技术要点。本书通过生动有趣的比喻,将抽象的编程概念...

    悟透javascript(精简版)

    ### 悟透JavaScript核心知识点解析 #### 一、编程世界的本质:数据与代码 在《悟透JavaScript(精简版)》这本书中,作者李战(leadzen)以独特的视角探讨了编程世界的本质——数据与代码之间的关系。他通过生动的...

    悟透JavaScript.rar

    "悟透JavaScript"这份教程资料,对于初学者和有志于成为专业前端开发者的人员来说,无疑是一份宝贵的资源。通过系统学习这份教程,可以深入理解JavaScript,并在网页制作中实现各种丰富的交互功能。 JavaScript的...

    悟透JavaScript.chm

    悟透JavaScript 在软件工业迅猛发展的今天,各式各样的编程语言层出不穷,新语言的诞生,旧语言的演化,似乎已经让我们眼花缭乱。为了适应面向对象编程的潮流,JavaScript语言也在向完全面向对象的方向发展,新的...

    悟透JavaScript

    资源名称:悟透Javascript内容简介:翻开此书的你,也许是Javascript的崇拜者,正想摩拳擦掌地想尝试下学一学这一精巧的语言;也许是80后,90后的程序员或者前端架构师,正被Javascript魔幻般的...

    一个月悟透JavaScript

    "一个月悟透JavaScript"这本书显然旨在帮助读者在短时间内深入理解和掌握这门语言的精髓。JavaScript以其灵活、动态的特性,使得网页交互变得更加丰富和生动。下面,我们将根据书名和描述,探讨JavaScript的一些关键...

    悟透JavaScript.pdf

    ### 悟透JavaScript核心知识点解析 #### 一、编程世界的本质:数据与代码 **悟透JavaScript**这本书深入探讨了编程世界的核心——数据与代码之间的关系。在编程的世界里,一切皆可归结为这两种基本元素:数据与...

    悟透JAVASCRIPT 美绘本

    悟透 JAVASCRIPT 美绘本 插图版

    轻轻松松学用javascript编程 、悟透JavaScript

    "轻轻松松学用javascript编程" 和 "悟透JavaScript" 这两个主题,旨在帮助初学者和进阶者深入理解和掌握这门语言。 JavaScript的核心概念包括变量、数据类型、操作符、流程控制、函数和对象。变量是存储数据的容器...

    悟透javascript

    《悟透JavaScript:回归数据与代码的本原》 在《悟透JavaScript》一书中,作者李战(leadzen)引领读者深入理解JavaScript的核心概念,强调了编程世界中数据与代码的基本关系及其在JavaScript中的独特体现。本书...

    悟透JavaScript(PDF),脚本(超好教材)

    ### 悟透JavaScript——回归数据与代码的本质 #### 数据与代码:编程世界的两大基石 在探讨JavaScript之前,我们先从编程世界的基本构成入手。在编程的世界里,无论是哪种编程语言,都离不开两个核心要素:**数据*...

Global site tag (gtag.js) - Google Analytics