JavaScript学习记录

来源:互联网 发布:淘宝查gsx会泄露信息吗 编辑:程序博客网 时间:2024/05/17 06:40

1.构造函数

凡是能使用new操作符调用的,就是构造函数;不能使用new操作符调用的,就是普通函数(javas高级程序设计P146).

2.this对象

当在全局作用域中调用一个函数时,this对象总是指向Global对象(在浏览器中就是window对象)。

3.call()和apply()函数

1、每个函数都包含两个非继承而来的方法:apply()和call()。

2、他们的用途相同,都是在特定的作用域中调用函数。 

3、接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。

http://blog.csdn.net/hexon804/article/details/51322699详细查看

4.getAttribute()方法

一般情况下,都是通过元素的属性来获得元素的特性,而不使用getAttribute()方法。

5.element类型的attributes属性

element类型是唯一一个DOM节点类型。attributes属性中包含一个NamedNodeMap对象;
一般情况下不使用attributes的方法,但是如果需要遍历元素的特性时,使用attributes属性会很方便,因为它将元素的属性连接成一个集合。

6. null和undefined

如果要声明一个对象变量,而暂时不给它初始化,则可以将其指定为null值;null值表示的是一个空对象指针,所以使用typeof null 会返回object。
也就是说:只要意在保存对象的变量还没有真正保存对象,就应该明确的让该变量保存null值

7. toString()方法

num类型、boolean类型、string类型和object类型都有toString()方法;nullundefined没有toString()方法
如果不知道要转换的值是不是null或undefined,则可以使用String()方法,该方法可以将任何类型的值转换为为字符串
注:如果要把某个值转换为字符串,则可以将该值与""做加法:

8. object类型

object类型是所有它的实例的基础;也就是说object类型所具有的任何属性和方法也同样存在于更具体的对象中

9. 一元加和一元减操作符(+/-)

对一个数值应用该操作符时,数值会被转变为number类型,也就是会进行类型转换

10.加法操作和减法操作符

加法操作符:如果两个操作数中有一个操作数是字符串,则将另一个操作数转换为字符串,然后将两个字符串拼接起来
减法操作符:如果两个操作数中有一个操作数是字符串、布尔值、null或undefined,则在后台调用Number()函数将其转换为数值,然后进行减法操作。
注意:加法是将数值转换为字符串,减法是将字符串转换为数值

11.关系操作符

任何数值与NaN比较,都是返回false

12.相等操作符

不全等操作符(==)
tips:
  1. null 和 undefined是相等的
  2. 要比较相等性之前,不能将null和undefined转换为其他任何值
  3. 如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true。注意:即使两个操作符都是NaN,相等操作符也返回false;NaN不等于NaN
  4. 如果两个操作数都是对象,则比较他们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true;否则,返回false。
全等操作符(===)
全等操作符与不全等操作符的唯一区别:不全等操作符在比较之前会进行类型转换。
注意:null == undefined; 返回true。 但是 null === undefined; 返回false

13.for-in语句

是一种迭代语句,可以用来枚举对象的属性。
使用for-in语句之前,先确认该对象的值不是null或undefined。

14.with语句

with语句用于将代码的作用域设置到一个特定的对象中。
语法如下:with (expression) statement;
with语句会导致性能下降,不建议使用

15.switch语句

JavaScript中的switch语句除了拥有C语言中switch语句的特点外,还有用一下特性:
  1. 可以在switch语句中使用任何数据类型(C语言中只能使用数值),包括:对象,字符串。
  2. 每一个case的值不一定是常量,还可以是变量,甚至是表达式

15.函数

JavaScript中的函数特点:
  1. ECMAScript函数对传入进来的参数个数,以及参数类型没有要求。也就是说即使定义的函数形参个数为2个,实际传入3个也没有关系。造成这种现象的原因是由于ECMAScript函数中的参数在内部是用一个arguments对象来存储的;可以使用arguments[0]访问传入的第一个参数,以此类推。注意:arguments并不是Array数组的实例,只是与其类似
  2. arguments的值永远与命名参数(形参)的值保持同步
  3. 《JavaScript高级程序设计》第三版中说,修改命名参数不会改变arguments中对应的值;但是实际在chrome中测试,发现也会改变。
  4. ECMAScript中函数的参数传递的都是值,不可能通过引用传递参数。
  5. ECMAScript函数中没有函数签名的概念,因此其不支持函数重载

16.NodeList/NamedNodeMap和HTMLCollection

这三个集合都是“动态的”,也就是说每当文档结构发生变化时,它们都会得到更新,因此它们始终都会保存着最新、最准确的信息。
因此,我们经常看到如下for循环语句:
var divs = document.getElementsByTagName("div"),        i,        len,        div;//经常看到将for语句中,直接先取得length长度,如果直接将divs.length放到第二个变量的位置进行比较,//那么当文档更新时,也会更新length;for (i = 0, len = divs.length;  i < len; i++){    div = document.createElement("div");    document.body.appendChild(div);}
一般来说,应该尽量减少访问NodeList的次数。因为每次访问NodeList,都会运行一次基于文档的查询,会降低性能。所以一般都是考虑将从NodeList
中取得的值缓存起来
理解DOM的关键,就是理解DOM对性能的影响

17.复制基本类型变量和复制引用类型的变量

复制基本类型变量:
var num1 = 5;var num2 = num1;
num1和num2保存在两个独立的空间中,对他们任何一个操作,不会对另一个产生影响。
从一个变量向另一个变量复制基本类型的,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
num2中的值只是num1中5的一个副本


复制引用类型变量:
var obj1 = new Object();var obj2 = obj1;obj1.name = "Shaun";console.log(obj2.name);
obj1和obj2保存在两个独立的空间中,但是其指向同一片内存区间,对他们任何一个操作,会对另一个产生影响
复制引用类型的值时,也会将存储在变量对象中的值复制一份放到为新变量分配的空间中,但是,注意这个值的副本是一个指针,该指针指向存储在内
存堆中的一个对象,obj1和obj2将引用同一个对象

18. JavaScript中函数参数的传递都是按值传递

当传递基本类型的值时,直接把值(并不是值在内存中的地址)copy给函数中的局部变量(也就是arguments对象中的一个元素),因此在函数内部修改
参数的值对实参没有影响
而向参数传递引用类型的值时,传递的是这个值在内存中的地址,因此改变引用对象的值对实参有影响。


19. ECMAScript中没有块级作用域

如下:
for (var i = 0; i < 10; i++) {}alert(i);
在C语言中,i的作用于只限于for语句中,但是对于ECMAScript,在for语句外面i仍然有效


20.声明变量

使用var声明的变量会自动被添加到最接近的环境中。
  1. 在函数内部,最接近的环境就是函数的局部环境;
  2. 在with语句中,最接近的环境就是函数环境。
  3. 如果初始化变量时没有使用var声明,该变量会被自动添加到全局环境
  4. 如果局部环境中有与全局环境中同名的变量,则会使用局部环境中的变量
  5. 如果有一个操作数是对象,而另一个不是,就会在对象上调用valueOf()方法以取得基本类型的值,然后再根据查询规则获取变量的值

21. 垃圾回收

JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。
垃圾回收方法:
  1. 标记清除
  2. 引用计数:存在循环引用问题
实现方法:标记清除(基本上所有浏览器都使用标记清除方式,但是IE8-的COM对象使用的是引用计数,IE9解决了这个问题
实现原理:跟踪变量的执行,对不在有用的变量打上标记,周期性查询这些变量,根据标记进行内存释放。

注意:在IE中,JavaScript访问的COM对象依然使用的是引用计数的垃圾回收机制。

如下IE8及IE8以下版本使用COM对象与原生JavaScript时产生的循环引用问题
//以下函数存在循环引用的问题var element = document.getElementById("someElement");var myObject = new Object();myObject.element = element;element.someObject = myObject;//解决办法:在不使用他们的时候手动断开原声JavaScript对象与DOM元素之间的连接//将其指向null时,当垃圾收集器运行时,查询到了null就会回收他们占用的内存myObject.element = null;element.someObject = null;

22. 管理内存

思路:确保可以用最少的内存,让页面获得最好的性能
方法:只保存必要的数据,一旦数据不再有用,最好设置其值为null来释放其引用——解除引用。该方法适用于大部分全局变量和全局对象的属性,局部
变量在离开执行环境中时会自动解除引用。
注意:解除一个值得引用并不是释放其占用的内存空间,只是让其脱离执行环境,以便垃圾收集器下次运行时将其回收
function createPerson(name) {var localPerson = new Object();localPerson.name = name;return localPerson;}var globalPerson = createPerson("Shaun");//手动解除引用globalPerson = null;

23. 基本类型值和引用类型值特点:

  1. 基本类型值在内存中占用固定大小的空间,因此被保存在中;引用类型的值是对象,保存在堆内存中。(为什么?)
  2. 包含引用类型值得变量实际上包含的并不是对象本身,而是一个指向对象的指针
  3. 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象

24. 对象属性的访问方法

  1. 点操作符
  2. 使用方括号操作符
         方括号操作符的优点:1. 可以通过变量来访问属性,例如:                                                 
<span style="white-space:pre"></span>var propertyName = "name"; <span style="white-space:pre"></span>console.log(person[propertyName]);
2. 如果属性名中包含有空格,则只能使用方括号访问;同时属性名中是可以含有非数字非字母的,这时也只能是有方括号
注意:除非必须使用变量来访问属性,否则建议使用点操作符;使用字面量创造对象时,并不会调用Object()构造函数

      对象的创建方法:
  1. 使用构造函数 Object()
  2. 使用字面量
//方法一:使用Object()构造函数var person = new Object();person.name = "Shaun";person.age = 29;console.log(person);
//方法二:使用字面量var person2 = {name: "Shaun",age:29}console.log(person2);

25. Array类型

1. 创建数组的两种方式:
  • 使用构造函数Array();
  • 使用数组字面量
如下:
 // 创建数组的第一种方式:使用Array()构造函数 var colors = new Array(); console.log(colors); var colors = new Array(20); console.log(colors); var colors = new Array("red", "blue", "green"); console.log(colors);// 创建数组的第二种方式:使用数组字面量var colors = ["red", "blue", "green"];var names = [];//创建一个空数组

2. 数组的特点
  • 数组的大小是可动态调整的
  • 数组的length属性不只是可读,同时也可写;通过操作length可以在数组末尾移除项或向数组中添加新项

3. 数组继承的toString()、valueOf()和toLocaleString()方法
这三个方法在默认情况下都会以逗号分隔的字符串的形式返回数组项。而如果使用join()方法,则可以使用不同的分隔符来构建这个字符串。join()方法只
接收一个用作字符串分隔符的参数,然后返回包含所有数组项的字符串

4.排序
可以使用sort()方法 + 自定义的compare函数进行排序,如下:
function <strong>compare</strong>(value1, value2) {    //升序,如果需要降序排列,可以修改compare函数if (value1 < value2 ) {return -1;}else if (value1 > value2) {return 1;} else {return 0;}}var values = [0, 1, 10, 3, 2, 17, 5];values.sort(<strong>compare</strong>);console.log(values);

5. splice()和slice()方法

26. RegExp类型

有如下两种创建方式:
  1. 使用字面量
  2. 使用构造函数
//匹配第一个"bat"或"cat", 不区分大小写var pattern1 = /[bc]at/i;//与pattern1相同,使用构造函数创建var pattern2 = new RegExp("[bc]at", "i");

注意:传递给RegExp构造函数的两个参数都是字符串(不能把正则表达式字面量传递给ExgExp构造函数)。由于RegExp构造函数的模式参数是字符串
,所以在某些情况下要对字符进行双重转义。所有元字符都必须双重转义。如字符\在字符串中通常被转义为\\,而在正则表达式字符串中就会变成\\\

27. Function类型

特点:
  1. 函数也是对象;每个函数都是function类型的实例,与其他引用类型一样,具有属性和方法;因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定
  2. 使用不带圆括号的函数名是访问函数指针而非调用函数
  3. 理解:函数是对象,函数名是指针;函数名本身就是一个变量,所以它具有变量的一切特性
  4. 函数声明和函数表达式:在代码开始执行之前,解析器通过一个名为函数声明提升(function declaration hoisting)的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部。所以,即使声明函数的代码在调用它的代码后面,JavaScript引擎也能把函数声明提升到顶部

函数内部属性:
  1. 函数内部有两个特殊的对象:arguments和this,还有一个caller属性()
  2. arguments对象主要保存传入函数的参数,还有一个名叫callee的属性,该属性是一个指针,指向正在执行的函数的指针;另外还有caller属性,该属性中保存着调用当前函数的函数的引用

如下:
//阶乘通用实现function factorial(num) {if (num <= 1) {return 1 ;} else {return num * factorial(num - 1);}}//使用callee属性实现阶乘,将函数执行和函数名分离,推荐使用 function factorial (num) { if (num <= 1) { return 1;  } else {  return num * arguments.callee(num - 1);  } }
this属性:引用的是函数据以执行的环境对象。因为在函数内部有函数的执行环境,全局环境中有window环境(全局作用域),this指的就是当前引用的执行环境
实例:
window.color = "red";var o = { color: "blue"};function sayColor() {console.log(this.color);}//在window执行环境中sayColor();// "red"//在o对象的执行环境中o.sayColor = sayColor;//添加sayColor方法o.sayColor();//"blue";
注意:函数的名字仅仅是一个包含指针的变量而已。因此上面例子,即使在不同的环境中执行,全局的sayColor()函数与o.sayColor()指向的仍然是同一个函数,只是因为他们的执行环境不同,所有导致了不同的结果。

函数的call()和reply()方法:用于在特定作用域内执行函数。其真正强大的地方在于能够扩充函数赖以生存的作用于。
如:
window.color = "red";var o = { color: "blue"};function sayColor() {console.log(this.color);}sayColor();//red, 全局函数,所以在全局作用域中,也就是window.colorsayColor.call(this);//red,在全局作用域中调用sayColor.call(window);//red,在全局作用域中调用sayColor.call(o);//blue,在o对象的作用域中调用

bind()方法:创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
如:
window.color = "red";var o = {color: "blue"};function sayColor() {console.log(this.color);}// 绑定objectSayColor函数的this到o的作用域上 var objectSayColor = sayColor.bind(o);objectSayColor();//blue 

28. 基本包装类型

  1. 布尔表达式中的所有对象都会被转换为true;

29. 构造函数

1. 任何函数,只要通过new操作符来调用,那它就是构造函数;其他函数,一般不通过new操作符来调用
2.通过构造函数创建一个对象实例时,实例中的指针指向的是对象原型,而不是构造函数。

30. for...in循环

使用for-in循环时,返回的是所有能够通过对象访问的、可枚举的(enumerated)属性,既包括存在于实例中的属性、也包括存在于原型中的属性。

31. 原型与实例

如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

32. 构造函数、原型和实例的关系:

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针

33. 闭包

指有权访问另一个函数作用域中的变量的函数(太书面化了)。
闭包函数:在一个函数内部创建另一个函数
作用域链:闭包的作用域链包含着它自己作用域、包含函数的作用域和全局作用域
function assignHandler() {var element = document.getElementById("someElement");element.onclick = <strong>function() {<span style="white-space:pre"></span>//闭包,匿名函数console.log(element.id);}</strong>}assignHandler();

34.立即执行函数和匿名函数

将函数声明包括在一对圆括号中,表示它是一个函数表达式。在其后紧跟另一对圆括号,表示立即调用这个函数。
要将函数声明转换为函数表达式,只需要将它包围在一对圆括号中。
在匿名函数中定义的任何变量,都会在执行结束时被销毁
如:
function outputNumbers02(count) {<strong>(function(){<span style="white-space:pre"></span>//立即执行函数for (var i = 0; i < count; i++) {console.log(i);}})()</strong>;var i ;console.log(i);}outputNumbers02(10);

35.全局变量和window对象上的属性

1. 定义全局变量与直接在window对象上直接定义属性有一点差别:全局变量不能通过delete操作符删除,而直接在window对象上定义的属性可以。
如:
var age = 29;window.color = "red";console.log(delete window.age);//返回falseconsole.log(delete window.color);//返回trueconsole.log(window.age);//29console.log(window.color);//undefined
2. 尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。
例如:
//这里会抛出错误,因为oldValue未定义var newValue = oldValue;//这里不会抛出错误,因为这是一次属性查询//newValue的值时undefinedvar newValue = window.oldValue;

36. 事件处理程序

DOM0级事件处理程序
var btn = document.getElementById("myBtn");<strong>btn.onclick</strong> = function() {<span style="white-space:pre"></span>//添加事件alert("Clicked");
<pre name="code" class="javascript" style="font-size: 14px; line-height: 25.2px;"><strong>btn.onclick</strong> = null;<span style="white-space:pre"></span>//移除事件

DOM2级事件处理程序:
 var btn = document.getElementById("myBtn"); btn.<strong>addEventListener</strong>("click", function(){<span style="white-space:pre"></span>//添加事件 alert(this.id); },false);
  <strong>btn.removeEventListener</strong>("click", function(){<span style="white-space:pre"></span>//移除事件 alert(this.id); },false);
IE事件处理程序:
  btn.<strong>attachEvent</strong>("onclick", function(){<span style="white-space:pre"></span>//添加事件1,后执行 alert("hello world"); alert(this === window);<span style="white-space:pre"></span>//true; this指向window });
 btn.attachEvent("onclick", function() {<span style="white-space:pre"></span>//添加事件2,先执行 <span style="white-space:pre"></span>alert("Clicked"); })
这两个事件按相反的顺序执行

注意:1 . 在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。
在DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行,也就是this指向添加事件的元素
在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,也就是this指向window
2. 在IE事件处理程序中,当为一个元素添加两个事件时,事件的执行并不是像DOM0或DOM2级事件处理程序一样按顺序执行,而是按像反的顺序
执行

37. 事件委托

指利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。如:click事件会一直冒泡到document层次上,所以我们可以给
document添加一个click事件, 然后在里面判断事件时来自于哪个元素

38. document.getElementsByTagName("error")[0].firstChild.nodeName的使用

注意:当error节点没有子节点时,firstChild返回的是null,对null没有nodeName属性,所以会出现错误;
如果需要判断error节点是否有某节点,可以使用
document.getElementsByTagName("error")[0].childNodes.length;获取子节点的长度,然后进行判断




























1 1
原创粉丝点击