作者:禅楼望月(http://www.cnblogs.com/yaoyinglong

1. 基本类型和应用类型

1.1 复制变量值的不同

值类型的变量在复制变量值后互不影响,因为值类型本身保存的就是等号后面的实实在在的值。所以它将自己的值复制给对方。

引用类型则不然,因为它保存的是等号后面的Object对象在对内存中的地址。所以当它给别的变量赋值时,也是将自己仅有的Object对象地址赋值过去。所以在赋值以后前后两个变量都保存的是同一个Object对象在对内存中的地址。

1.2 传递参数

所以下面这段代码:

而下面这段代码:

这是为什么呢?

我们来分析一下这段代码。首先定义了一个person对象,为它动态添加了一个name属性并赋值为“angel”,然后调用changePersonName函数,将person作为实参传递给changePersonName函数,person是引用类型,所以按引用类型的赋值规则是将person对象在内存中的地址传递过去。此时changePersonName函数的形参p的值是person对象在内存中的地址。但是刚进入该函数,p=new Object();这段代码,让p发生了翻天覆地的变化。它将p的值换掉了,原来p存的是person在内存中的地址。它和外部的person都指向这块地址,但是经过这段代码之后,它切断了指向person的指向,指向到了一个新的Object实例在内存中的地址。此时的p和外围的person没有任何关系了。所以改变它不会对外围的person起到任何作用。

1.4 类型检测

typeof:typeof一般只能返回如下几个结果(6种):number,boolean,string,function,object,undefined。

在JavaScript中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回"object"。因此引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。

另外,更重的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。

2. 执行环境和作用域

2.1 执行环境

总所周知,函数能够访问

①声明在当前函数作用域“之外”的变量;

②全局变量;

③声明在函数内部的变量以及;

④通过参数传进来的变量;

⑤指向“容器对象”的"this"变量。

以上所有这些变量为我们的函数形成了一个“环境”,该“环境”定义了哪些变量和它们的值是可以被当前函数访问的。一部分“环境”是随着函数的定义而定义的,其他一些是函数访问的时候才定义的。

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境中有一个变量对象与之对应,该环境中所有变量和函数都保存在这里。虽然编程是不能使用,但是在解析器在处理数据是会用到。

所有全局变量和函数都作为window对象的属性和方法创建。某个执行环境的所有代码执行完毕,该环境也就被销毁了。

作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。(这对理解闭包很重要)

2.2 JS没有块级作用域

JS中的局部块只有函数(function)可以创建,其他语句不能如if(){}、for(){}、with(){}等等即使有大括号,但是在这些大括号里面创建的变量不是它自己的布局变量。而是属于上一级函数的变量。因此就具有了延长作用域链。

3. 闭包

闭包的表现形式:多是在一个函数里面创建另一个函数

该内部函数被返回了,但是它在外部被调用的时候任然能访问到包含它的函数的变量。这是因为当函数第一次被调用的时候会创建一个执行环境和相应的作用域链,然后将作用域链赋值给它的一个内部属性(Scope。然后使用this、arguments和其他命名参数的值来初始化函数的活动对象。自己的活动对象句第一位,外部函数的活动对象居第二位,……

当内部函数被外部函数返回时,它的作用域链包含外部函数的活动对象和全局变量对象。更为重要的是虽然外部函数执行完毕,但是它的活动对象也不会被销毁(一般情况下当函数执行完毕后它的局部活动对象就会被销毁),因为返回来的内部函数的作用域链任然在引用这些活动对象。即,当外部函数执行完毕,它的作用域链会被销毁,但是活动对象不会被销毁,直到返回来的内部函数也被销毁后,外部函数的活动对象才会被销毁。

3.1 this

由于闭包的执行环境是全局的。所以在闭包中访问不到object的作用域链。才造成打印出来的是“The Window”,要避免这种情况即,让闭包能访问到object的作用域链,在匿名函数中申明以变量即可,将this付给这个变量对象。

在这里that的作用域链的前端是object。所以它首先访问到的是object的name。

注:这里的this指的是在function当做函数来使用的时候,但是当函数被当作构造器使用时,this指的是该对象。

[+]view code
function person(){
    this.name="name";
    this.age="age";
}
person();

alert(name);//打印的结果为:“name”

这是因为person是全局函数,因此在它中的this指的就是包含它的对象,即window。这时,name和age变成为全局变量了。而当person被当作构造函数来使用的话,this就代表被构造出来的对象:

[+]view code

function person(){

    this.name="name";
    this.age="age";
}
//person();
var p=new person();
alert(name);

alert(p.name);

由此我们可以得出:this指的是包含该函数的对象。对于全局函数来说,包含它的是window;对于构造器和对象中的方法来说包含它的是将被构造出来的对象;对闭包来说,包含它的对象也是window。

3.2 私有变量和私有函数

JS中在函数中定义的变量都可以认为是私有的变量。

其中Person中的name和ss都是私有的,实例化Person后也不能访问这两个变量。

但是下面用this添加的变量在实例化后可以直接访问。

所以可以将一些不必让外部访问的变量用var来声明,无需用this来添加属性。外部要访问这些私有变量可以为其设置一个特权函数(即一个匿名函数):

3.3 闭包与变量

闭包的实现就是以来作用域链,但是作用域链的本质是指向变量对象的指针列表。所以,闭包只能取到外部函数中任何变量对象的最后一个值。

打印出来的都是10.

虽然在中,外部函数已经执行完毕,一般情况下它的局部变量对象会被销毁,但是由于被返回的匿名函数依然引用这它的活动变量i,所以外部活动变量i任然存在

当后面每次调用返回来的匿名函数时:相当与在执行function(){return i;}函数,它首先会在自己的活动变量中寻找i,没找到,然后在它的外部函数中寻找活动变量i,但是此时由于执行了语句,使得i的值为10.所以内部匿名函数也就返回了10.每次调用内部匿名函数都会执行同样的上述流程。

那么怎么来避免这种情况呢?

首先来看一个一直未用过的技巧:

不能在函数中直接写匿名函数,除非将匿名函数赋值给一个变量或者用括号括起来,但是在函数外面可以直接写。

在这里ss不在代表的是匿名函数了,而是该匿名函数被执行所返回的东西,所以ss在这里已经被赋值位“立即执行”了。所以匿名函数可以在后面增加括号来传递参数立即执行。

所以我们在外部函数中让内部匿名函数立即执行:这里又有两种情况:

· 1.result中包含的是值。

在这里我们将result数组的内容改变了,它每一项中不在保存由返回来的匿名函数或者闭包。而是内部匿名函数执行后的值。

· 2.result中包含的是闭包

我们来看一下这个函数的执行过程,当执行时,“result[i]=”后面的闭包由一个立刻被执行的匿名函数代替。该匿名函数同样返货一个闭包。而该闭包返回的是匿名函数的活动对象,而不是的活动对象,而是的活动对象。的作用域链及所有活动对象当然包括i,在执行完毕后被销毁。而该匿名函数的活动对象sum是通过每执行一个i++,将此时的i的快照赋值给了sum,注意,这里i是值类型并且JS中传参是按值传递的,所以i++不会影像到前一个sum。

所以result[i]=,该闭包在自己的活动对象中找不到sum,便在它的包含函数中找sum,此时的中的sum已经在的for语句时赋了值。而每次的i++中之间没有任何关系。所以,sum也就不会被替换了。

4. Arrary

创建数组有两种方法:

①使用Array构造函数:

var colors=new Array();或者var colors=new Array(20);(这里是创建一个包含20个项的数组)或者var colors=new Array("red","blue");(这里是创建了一个包含 "red"和"blue"2个字符串的数组 )当然也可以将new去掉。

②使用数组字面量表示法:

打印:

注意:数组的length属性不是只读的,可以修改它来控制数组的长度。没有赋值的项为undefined。也可以利用该属性方便的在数组的末尾添加新项:

打印:

这是因为,数组的最后一项的索引为length-1,则在数组末尾再加一项,它的索引变为length。

4.1 重排序

两个方法:

①reverse

用途:反转一个数组,返回值为反转后的数组。

打印:

②sort

默认情况下是按照升序排列的。返回排序后的数组。

打印:

打印:

由此可见sort默认的比较是按照字符串来比较的。之所以将5排在10和15之后,对于字符串来说,“5”排在“1”之后。

为了克服这种不便,sort还可以接受一个比较函数作为参数,以便我们指定那个值位于那个值的前面。该比较函数接受两个参数,如果第一个参数位于第二个参数的前面则返回一个负数,如果两个参数相等则返回0,如果第一个参数位于第二个参数的后面则返回一个整数。编写一个比较函数来排序上面这个数组:

打印:

如果数组的每一项都是数值的话则可以用如下更简便的比较函数:

5. 绑定上下文

[+]view code

var theAccumulator={

,
   clear:function(){
;
   },
   add:function(x){
     this.total+=x;
   },
   getResult:function(){
     returnthis.total;
   }
};
function printResult(f){
   alert("result="+f());
}
theAccumulator.clear();
);
);
printResult(theAccumulator.getResult);

最后一句代码,我们期望的接货时弹出:result=300,但是事与愿违,弹出的结果却是:

为什么会这样呢?因为当把theAccumulator.getResult传递给printResult的时候没有为theAccumulator.getResult设置上下文,要知道“JavaScript函数并不与定义它们时的作用域绑定,它们对执行它们时的作用于的要求并不严格。”所以在theAccumulator.getResult函数中返回this.total,这时,在没有明确的作用域限制的情况下this指的是全局作用域。而在全局作用域中并没有total变量。所以才出现了上述情况。只要在全局作用域中增加total的定义:var total=100;,即代码更改为:

[+]view code

;

var theAccumulator={
,
clear:function(){
;
},
add:function(x){
this.total+=x;
},
getResult:function(){
returnthis.total;
}
};
function printResult(f)
{
alert("result="+f());
}
theAccumulator.clear();
);
);
printResult(theAccumulator.getResult);

将printResult函数变为如下即可:

还可以这样:

apply、call

强大之处:扩充函数赖以运行的作用域。

6. 面向对象

6.1 创建对象

在JS中创建对象的方法很多,但是每一种方法都有它自身的缺点,这里给出一个使用最广泛,认可度最高的一种方法:

[+]view code

functionPerson(name,age,job){

  this.name=name;
  this.age=age;
  this.job=job;
  this.friends=["Shelby","Court"];
}
Person.prototype={
  constructor:Person,
  sayName:function(){
    alert(this.name);
  }
}
 
,"programmer");
,"Doctor");
 
person1.friends.push("Van");
console.log(person1.friends);
console.log(person2.friends);
console.log(person1.friends===person2.friends);
console.log(person1.sayName===person2.sayName);

正如上面所演示的,使用构造函数定义实例属性,使用原型定义方法和共享的属性。这样每个实例都会有自己的一份实例属性的副本,同时也共享着对方法的引用,最大限度的节省了内存。

6.2 继承

JS中继承的实现方式也很多,这里同样也介绍一种最常用的方法。

使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例方法的继承。这样继承在原型上定义方法实现函数的复用,又能保证每个实例都有自己的属性。

[+]view code

functionSuperType(name){

  this.name=name;
  this.color=["red","blue","green"];
}
SuperType.prototype.sayName=function(){
  console.log(this.name);
};
 
functionSubType(name,age){
  //继承属性
  SuperType.call(this,name);
  this.age=age;
}
//继承方法
SubType.prototype=newSuperType();
SubType.prototype.sayAge=function(){
  console.log(this.age);
}
 
);
instance1.color.push("black");
console.log(instance1.color);
instance1.sayName();
instance1.sayAge();

7. Ajax

AJAX 就是运用Javascript 在后台悄悄帮你去跟服务器要资料,最后再由Javascript 或DOM 来帮你呈现结果,因为所有动作都是由Javascript 代劳,所以省去了网页重载的麻烦,使用者也感受不到等待的痛苦。

7.1 XMLHttpRequest对象简介

XMLHttpRequest对象是Ajax应用程序的中心。

• XMLHttpRequest对象最初是作为IE5中的一个ActiveX控件出现的,随后Mozilla 1.0、Netscape7、Safari1.2和Opera7.60都将它纳入自身。

• XMLHttpRequest对象在IE浏览器和非IE浏览器中创建的方法不同。

• XMLHttpRequest对象的作用在于,允许用脚本程序通过HTTP连接到服务器,而不是通过HTTP请求响应模型与服务器通信。

简而言之:它可以异步从服务器端获取txt或者xml数据

• 开发一个AJAX功能需要开发服务端和客户端两块程序。以一个显示服务端时间为例。首先开发一个GetDate1.action,输出当前时间。在HTML页面中放一个按钮,在按钮的onclick中创建XMLHTTP向GetDate1.action发送请求,获得返回的数据并且显示到界面上。代码见备注。

• 也可以在xmlhttp.open中向服务器传递参数:xmlhttp.open("POST", "GetDate1.action?id=1&name=哈哈", true),如果传递给服务器的请求里有中文,则需要使用Javascript函数encodeURI来进行URL编码。

7.2 创建XMLHttpRequest对象

同步使用XMLHttpRequest对象

按照下面模式,可以同步地XMLHttpRequest对象:

  1. 创建对象; - new  (叫助手过来)
  2. 创建请求; - open (告诉他要去做的事情)
  3. 发送请求; - send (去吧)

一、先来创建XMLHttpRequest对象

– 在IE、Firefox、safari和Opera中创建该对象的JavaScript代码为:var xhr = new XMLHttpRequest();

– 在IE5/6中代码为:var xmlRequest = new ActiveXObject(“Microsoft.XMLHTTP”);

注意,JavaScript区分大小写。

[+]view code

function createXmlHttp(){//创建xhr对象

var xhobj =false;
try{
  xhobj =newActiveXObject("Msxml2.XMLHTTP");// ie msxml3.0+
}catch(e){
  try{
    xhobj =newActiveXObject("Microsoft.XMLHTTP");//ie msxml2.6
  }catch(e2){
    xhobj =false;
  }
}
 
if(!xhobj &&typeofXMLHttpRequest!='undefined'){// Firefox, Opera 8.0+, Safari
  xhobj =newXMLHttpRequest();
}
  return xhobj;
}

二、为XMLHttpRequest对象设置请求参数

1.设置参数:
xhr.open("GET", "GetAreasByAjax.action?isAjax=1", true);

2.POST方式:
xhr.open("POST", "GetAreasByAjax.jsp", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

3.设置浏览器不使用缓存
xhr.setRequestHeader("If-Modified-Since", "0");

三、发送请求:(分别对应GET和POST)

xhr.send(null);//GET方式

xhr.send("isAjax=1&na=123");//POST方式

异步使用XMLHttpRequest对象

异步使用XMLHttpRequest对象时,必须使用:onreadystatechange事件。

使用模式应该是:

  1. 创建该对象;-new
  2. 设置readystatechange事件触发一个回调函数; -onreadystatechagne
  3. 打开请求;-open
  4. 发送请求;-send
  5. 在回调函数中检查readyState属性,看数据是否准备就绪(是否等于4)。

如果没有准备好,隔一段时间再次检查。因为数据没有下载完时,我们无法使用它的属性和方法。

如果已经准备好,就继续往下执行;

7.3 编写回调函数

1.在xhr.send之前添加设置回调函数代码:

xhr.onreadystatechange = watching;

2.回调函数

[+]view code

function watching(){

){
){
      var msg = xhr.responseText;//服务器返回的字符串
    }else alert("服务器错误!"+ ajaxH.status);
  }
}

7.4 XMLHttpRequest对象常用属性

readyState属性指出了XMLHttpRequest对象在发送/接收数据过程中所处的几个状态。XMLHttpRequest对象会经历5种不同的状态。

– 0:未初始化。对象已经创建,但还未初始化,即还没调用open方法;

– 1:已打开。对象已经创建并初始化,但还未调用send方法;

– 2:已发送。已经调用send 方法,但该对象正在等待状态码和头的返回;

– 3:正在接收。已经接收了部分数据,但还不能使用该对象的属性和方法,因为状态和响应头不完整;

– 4:已加载。所有数据接收完

7.5 XMLHttpRequest对象的方法

7.6 实例-get

Js生成XMLHttpRequest

[+]view code

function createXmlHttp() {//创建xhr对象

var xhobj = false;

try {

xhobj = new ActiveXObject("Msxml2.XMLHTTP"); // ie msxml3.0+

} catch (e) {

try {

xhobj = new ActiveXObject("Microsoft.XMLHTTP"); //ie msxml2.6

} catch (e2) {

xhobj = false;

}

}

if (!xhobj && typeof XMLHttpRequest != 'undefined') {// Firefox, Opera 8.0+, Safari

xhobj = new XMLHttpRequest();

}

return xhobj;

}

var xhr = false;   //全局变量来接收生成的XMLHttpRequest

window.onload = function () {

xhr = createXmlHttp();

}

点击按钮执行Ajax调用:

[+]view code

<input type="button" value="Ajax请求" onclick="doAjax()" />

function doAjax() {

//第二步:为XMLHttpRequest对象设置请求参数

xhr.open("GET", "AjAxTest.jsp?isAjax=1", true);

//第三步:设置回调函数

xhr.onreadystatechange = watching;

//第四步:发送请求

xhr.send(null);

}

function watching() {

if (xhr.readyState >= 4) {

即,成功返回没有任何错误时

var txt = xhr.responseText; //服务器返回的字符串,即Response.Write();的内容。

document.getElementById("divMsg").innerHTML = txt;

}

else {

document.getElementById("divMsg").innerHTML = "服务器出错了?";

}

}

}

7.7 实例-post

[+]view code

var xhr;

window.onload = function () {

xhr = createXmlHttp();

document.getElementById("btnL").onclick = loginByAjax;

}

function loginByAjax() {

var uName = document.getElementById("txtUName").value;

var uPwd = document.getElementById("txtPwd").value;

var urlStr = "DoLogin.action";

var data = "uname=" + uName + "&upwd=" + uPwd;

  xhr.open("POST", urlStr, true);

xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) {

if (xhr.status == 200) {

var txt = xhr.responseText;

if (txt == "1") {

alert("登录成功");

window.location= "Default.jsp";

}

else {

alert("登录失败");

}

}

else {

alert("服务器错误!xhr.Status=" + xhr.status);

}

}

}

xhr.send(data);

}

JavaScript 回忆录的更多相关文章

  1. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  2. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  3. Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

    执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...

  4. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  5. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  6. 《Web 前端面试指南》1、JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

  7. JavaScript权威指南 - 函数

    函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...

  8. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  9. JavaScript进阶之路(一)初学者的开始

    一:写在前面的问题和话 一个javascript初学者的进阶之路! 背景:3年后端(ASP.NET)工作经验,javascript水平一般般,前端水平一般般.学习资料:犀牛书. 如有误导,或者错误的地 ...

随机推荐

  1. DOJO-dojox.grid.EnhancedGrid(带刷新函数,分页工具栏,复选框,行号等功能)

    转自:http://biancheng.dnbcw.info/javascript/395865.html dojo.require("dojox.grid.EnhancedGrid&quo ...

  2. openSUSE 11 上的配置可以Xmanager远程桌面

    openSUSE 11 上的配置(适用于默认图形环境为KDE的Linux): 1.配置KDM. openSUSE 11的默认图形环境为KDE,虽然可以同时安装GDM和KDM,但默认只启动了KDM.所以 ...

  3. Java中的受检异常

    Java中的受检异常 Java提供了三种异常类型,受检异常(checked exception).运行时异常(runtime exception).错误(error).那么这受检异常在实际开发中又有什 ...

  4. .Net Core CLI windows安装

    下载官方的msi安装包official MSI installer双击安装就可以了. 默认会安装到C:\Program Files\dotnet\目录下,如果找不到可以用命令 where dotnet ...

  5. phpmyadmin Wrong permissions on configuration file, should not be world writable!

    巴拉巴拉,实际场景是这样,因为有需要,所以想用django 做个rest服务给其他平台提供服务,发现以前正常的页面都无法运行,奇怪发现有一个页面提示连接不上mysql 难道mysql挂了,打开phpm ...

  6. git/ssh捋不清的几个问题

    主要是 windows 用户会遇到很多纠结的问题,linux/unix 用户属于这方面的高端用户,应该有能力处理此类问题,而且网络上也有很多解决方案,本文的授众是 windows 用户.由于今天配置了 ...

  7. JavaScript工具库之Lodash

    你还在为JavaScript中的数据转换.匹配.查找等烦恼吗?一堆看似简单的foreach,却冗长无趣,可仍还在不停的repeat it!也许你已经用上了Underscore.js,不错,你已经进步很 ...

  8. 线程池ThreadPool知识碎片和使用经验速记

    ThreadPool(线程池)大概的工作原理是,初始时线程池中创建了一些线程,当应用程序需要使用线程池中的线程进行工作,线程池将会分配一个线程,之后到来的请求,线程池都会尽量使用池中已有的这个线程进行 ...

  9. javascript日常总结

    如何去除掉inline-block元素之间的默认间距 前几天写一个页面 1 2 3 4 div{width:900px;} div li{ display:inline-block; width:30 ...

  10. 程序员藏经阁 Linux兵书

    程序员藏经阁 Linux兵书 刘丽霞 杨宇 编   ISBN 978-7-121-21992-4 2014年1月出版 定价:79.00元 536页 16开 内容提要 <Linux兵书>由浅 ...