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

js笔记—— 基础部分一

2016-05-25 17:17 344 查看
前言:js由三部分组成,1. 核心(ECMAScript),语法标准    2.文档对象模型(DOM)    3.浏览器对象模型(BOM)

JavaScript 的核心语言特性在ECMA-262中是以名为ECMAScript的伪语言的形式来定义的。ECMAScript中包含了所有基本的语法,操作符,数据类型以及完成基本的计算任务所必需的对象,但没有对取得输入和产生输出的机制作出规定。

1.在web中引入js

<script></script>    使html与js混合

defer  :  延迟到页面全部解析完后再加载js

type : mime类型, 默认"text/javascript"。可省略

引入外部js:

<script src=""></script> 可引入不用域的js,引入外部js时同时在标签内嵌入js代码会被忽略。

 注意:不要在js中出现 </script> ,会造成浏览器错误解析(以为js已经结束)。

 小tips:浏览器按照<script>标签先后顺序解析,如果将js代码放head里,浏览器会先解析js,然后呈现body中的页面元素(页面延迟,呈现空白)

2.数据类型

ECMAScript 中规定的5种基本数据类型:  Undefined,Null,Boolean,Number,String

      1种复杂数据类型:  Object   由一组无序的键值对组成

typeof操作符: 用于返回检测的变脸类型   :  undefined,object,boolean,number,string,function

typeof(null); //返回"object"  空对象指针(对空对象的引用)

Undefined类型

只有一个值  undefined,变量声明后未初始化,值就是undefined。(未声明和声明后未定义值都是undefined)
var name;
alert(name);//"undefined"
alert(age);//"undefined"

Null类型

同样只有一个值  null。
var name = null;
alert(typeof  name);//"object" 对空指针的引用
小tips:在定义一个变量用来保存对象时,初始化时最后给null,这样就只需要检查null值就可以判断变量是否保存了对象的引用.
  如:

var person = null;
if(person!=null){

}
alert(null == undefined); //true,  undefined值是派生自null值的

Boolean类型

任何其他类型都有与Boolean等价的值
Boolean(""); //false,   非空字符串返回true
Boolean(0);//0和NaN 返回 false ,   非零(包括无穷大)返回true
Boolean(null);//返回false
Boolean(undefined);//false

使用if语句进行流程控制时,会自动调换用Boolean()函数进行转换

Number类型

var num1 = 55;  //十进制
var num2 = 070; //八进制  0开头   56
var num3 = 0x1f; // 十六进制  0x开头   31

浮点数值

由于保存浮点数值需要的存储空间是整数值的两倍,所以ECMAScript会尽可能将浮点数转成整数。

var floatNum1 = 10.0; //保存的是整数10

注意:0.1+0.2 !=0.3 浮点数精度问题(永远不要测试某个特定的浮点数值)

2. 数值范围

Number.MAX_VALUE,Number.MIN_VALUE,Number.NEGATIVE_INFINITY,Number.POSTIVE_INFINITY

Infinity正无穷, -Infinity负无穷。

isFinite()函数来判断是否在这个范围内,超出范围的数值会被自动转成相应的无穷大值

3. NaN(Not a Number)非数值

任何数值除以0返回NaN,不会抛错(不会影响后面代码的执行)

注意:任何涉及NaN的操作都会返回NaN。NaN与任何值都不相等(包括NaN)

alert(NaN == NaN); //false

isNaN();//判断是否 "不是数值"

alert(isNaN(NaN));  // true
alert(isNaN(10));  //false
alert(isNaN("10"));  //false,可转换成数值
alert(isNaN("blue"));  //true,不可转成数值
alert(isNaN(true));    //false 可转成数值

4. 数值转换函数 Number() ,parseInt()和parseFloat()

Number(null); // 0

Number(undefined); //NaN

Number("hehe"); //NaN

Number(""); //0

parseInt("0xAF",16); //175

parseInt("AF"); //NaN 需指定进制

parseInt("10",2); // 2 (二进制)

String 类型

由零或多个 16位 Unicode字符组成的字符序列

注意:字符串一旦创建,值就不能改变。如果改变,是先销毁原来的字符串,然后用新字符串来填充该变量

字符串转换:

toString();几乎每个值都有该方法

toString(2); //可指定数值的转换进制

null和undefined没有 toString()函数

可以使用String()函数来转换:String(null); // "null"

String(undefined); //"undefined"

Object类型 (所有对象的基础)

Obejct属性和方法

Constructor:构造函数(用于创建当前对象的函数)

hasOwnProperty(propertyName):检索当前对象实例中的属性(不是实例原型)是否存在,参数必须是字符串

isPrototypeOf(object):传入的对象是否是另一个对象的原型

propertyIsEnumerable(propertyName):属性是否能用for-in 遍历

toLocalString():返回对象的字符串表示

toString():

valueOf():返回对象的字符串,数值或布尔值表示。通常与toString()返回相同

3.操作符

1.位操作符

32位二进制表示整数,第32位为符号位

~ 按位非(NOT)

& 按位与(AND)

| 按位或(OR)

^ 按位异或(XOR)

<< 左移,不影响符号位

>> 有符号右移,保留符号位,不影响正负

<<< 无符号右移,连着符号位一起右移

2.关系操作符

4.语句

1.for-in 精准的迭代语句,可以用来枚举对象的属性

for(var propName  in window){
document.write(propName);
}


输出BOM中 window对象的所有属性

迭代前最好先检测对象是否为null或undefined。(ECMAScript5中不执行循环体,以前会报错)

2.label语句,给代码添加标签

3.break和continue语句(break跳出循环,直接执行循环后的代码。continue跳出当前循环,接着进入下一次循环)

var num =0;
outer:
for(var i=0;i<10;i++){
for(var j=0;j<10;j++){
if(i == 5 && j==5){
continue   outer;
}
num++;
}
}
alert(num);    //95

4.  with语句(不建议使用,可读性差)

5. switch语句

var num = 15;
switch (true){  //输出  Between 10 and 20,如果是false就输出  Less than 0
case num<0:
alert("Less than 0");
break;
case num>=0&&num<=1:
alert("Between 0 and 1");
break;
case num>10&&num<=20:
alert("Between 10 and 20");
break;
default:
alert("More than 20");
}

6.函数

function关键字来定义函数,
注意:函数无所谓传进来多少个参数。因为在内部是用一个数组来表示的,在函数体内可以通过arguments来访问这个数组。
arguments对象只是与数组类似(并不是array的实例)
function doAdd(num1,num2){
arguments[1] = 10;    //会同步影响 num2的值,这种影响是单向的,反过来修改num2并不会影响arguments中的值
alert(arguments[0]+num2);
}

注意:arguments对象长度由传入的参数个数决定,不由定义函数时声明的参数个数决定,没有传值的参数自动赋值undefined

5.变量,作用域,内存

5.1  基本类型和引用类型

基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
基本类型是按值访问,所以可以操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象,js不允许直接 访问内存中的位置(不能直接操作对象的内存空间),实际操作的是对象的引用。

var person = new Object();
person.name = "张三";  //给引用类型变量动态添加属性并赋值
alert(person.name);//  张三
//无法给基本类型变量添加属性,不报错但是无效。


变量复制:  基本类型
var num1 = 5;
var num2 = num1;// num1和num2是两个独立的值,在进行任何操作时不会相互影响。
引用类型:

var obj1  = new Object();
var obj2 = obj1;
obj1.name = "张三";
alert(obj2.name);  // 张三
//obj1和obj2指向的是堆内存中的同一个对象



参数传递:

ECMAScript中所有函数的参数都是按值传递的。在传递基本类型值是,被传递的值会赋给一个局部变量(命名参数,arguments对象中的一个元素)

注意:传递引用类型时,会把这个值在内存中的地址赋值给一个局部变量(对堆内存中对象的引用),所以指向的还是同一个内存空间,因此对参数的修改会影响到函数外。

function setName(obj){
obj.name = "张三";//obj引用指向堆中的person对象,person.name = "张三"
obj = new Object();//给obj(参数,局部变量)  指向新的对象(该对象在setName函数中创建,是局部的,函数结束,对象销毁)
obj.name = "李四";//给obj引用的局部变量动态添加name属性赋值为"李四"
}
var person = new Object();
setName(person);
alert(person.name); //张三
类型检测:

通常用typeof来检测基本类型
instanceof来检测引用类型,根据它的原型链来识别。
所有引用类型都是Object的实例,用instanceof检测所有基本数据类型,都会返回false。基本类型 不是对象。

5.2 执行环境及作用域

说明:执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据是会在后台使用它。

全局执行环境是最外围的一个执行环境。在web浏览器中,全局执行环境就是window对象,因此所有全局变量和函数都是作为window对象的属性和方法

创建的。某个执行环境中的所有代码执行完后,保存在其中的变量和函数定义也随之销毁。

每个函数都有自己的执行环境。当执行流进入一个函数时,函数环境会被推入环境栈。执行完后弹出栈,控制权交给之前的执行环境

作用域链(scope chain)。保证对执行环境有权访问的所有变量和函数的有序访问

 
var color = "blue";
function changeColor(){
var anotherColor = "red";
function swapColors(){
var  temColor = color;
color = anotherColor;
anotherColor = temColor;
}
}

上面代码作用域链,如图:三个作用域,内部环境可以通过作用域链访问所有的外部环境

延长作用域链:

1.try-catch 中的catch块
2.with语句

function buildUrl(){
var qs = "?debug=true";
with(location){
var url = href + qs;  //location.href,url添加到最近的环境(buildUrl函数中)
}
return url;
}
with语句接收的是location对象,因此其变量对象中就包含了location对象的所有属性和方法,而这个变量对象被添加到了作用域链的前端,所以在函数内部可以访问。

没有块级作用域:

js没有块级作用域,不像java等语言,if(){},for(){}语句中定义的都是局部变量

for(var i=0;i<10;i++){
doSomething(i);
}
alert(i);   // 10
js中会将if,for中声明的变量添加到当前的执行环境中
变量声明:

使用var声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的就是当前函数的局部环境;在with语句中,最接近的环境是函数环境。如果初始化变量时没有var声明,则自动添加到全局环境。
function(num1,num2){
sum = num1+num2; //sum未声明,添加到全局环境
return sum;
}
var result = add(10,20); //30
alert(sum);    //30,可访问到


查询标识符:同名变量,从最近环境开始搜索,优先取最近环境中的值然后停止搜索。

5.3 垃圾收集

说明:JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存
局部变量只在函数执行的过程中存在。在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值。在函数执行结束,局部变量就没有存在的必要,因此可以释放它们的内存。

标记清除

JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境时(如:在函数中声明一个变量),就将这个变量标记为"进入环境",当变量离开环境时,则将其标记为"离开环境"。

垃圾收集器在运行的时候会给存储在内存中的所有变量加上标记,然后会去除环境中的变量以及被环境中的变量引用的变量的标记。

在此之后再被加上标记的变量将被视为准备删除的变量(环境中变量已经无法访问这些变量了)。最后,垃圾收集器完成内存清除工作,销毁带标记的值并回收内存空间。

引用计数

说明:引用技术会跟踪每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量,则这个值的引用次数就是1。如果该值又被赋给另外一个变量,则该值的引用次数加1。相反,如果对这个值引用的变量取得了另外一个值,则这个值的引用次数减一。当这个值的引用次数变成0的时候,就说明没法再访问这个值了,就可以将其占用的内存回收。当垃圾收集器下次再运行的时候就会释放这些空间。
问题:对象之间循环引用会造成内存无法回收

function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
A,B对象通过各自的属性相互引用。它们之间的引用次数永远不会是0。如果这个函数被重复多次调用,就会导致大量内存无法回收。

问题:IE中有一部分并不是原生JS对象,BOM和DOM中的对象就是使用C++以COM(Component  Object  Model,组件对象模型)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。所以,即使IE的JS引擎是使用标记清除策略,但JS访问的COM对象依然是基于引用计数策略的。这就照成只要在IE中涉及COM对象就会存在内存引用的问题。

var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.somObject = myObject;//DOM元素和JS对象相互引用,循环引用照成即使DOM从页面中移除,它也不会被回收。


可以通过赋值为null来手动断开这两个元素间的引用。如:

myObject.element =null;

element.somObject = null;

IE9中把BOM和DOM对象都转成了JS对象,也可以避免两种垃圾回收算法并存的问题(消除常见的内存泄漏现象)。

性能问题

说明:垃圾收集器是周期性运行的,原IE7策略问题:根据内存分配量运行,达到256个变量,4096个对象(或数组)或者64KB其中任一标准,垃圾收集器就会运行,这就导致如果一个脚本中包含这么多变量,那么这个脚本在器生命周期中很可能会一直保有这么多变量。这样一来,垃圾收集器就会频繁运行,导致性能急剧下降。

解决方法:如果回收的内存分配量低于15%,则临界值加倍。如果到了回收85%的内存分配量,就将临界值重置回默认值。这样循环往复,看似简单,实则极大提升了IE在运行包含大量JS的页面时的性能。

5.4 内存管理

说明:出于安全考虑,浏览器的可用内存数量比较少(防止运行JS的网页耗尽全部系统内存而导致系统崩溃)。内存限制不仅影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量。

tips:一旦数据不再有用,最好通过将其值设置为null来释放其引用(解除引用dereferencing)。该做法适用大多数全局变量和全局对象属性。局部变量会在它们离开执行环境时自动被解除引用

function createPerson(name){
var localPerson  = new Object(); //localPerson局部变量,不用手工解除
localPerson.name = name;
return localPerson;
}
var globalPerson = createPerson();
//手动解除globalPerson的引用
globalPerson = null;

解除globalPerson的引用,让值脱离执行环境,以便垃圾收集器下次运行时将其回收

小结:

基本类型值在内存中占据固定大小的空间,被保存在栈内存中
从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本
引用类型的值是对象,保存在堆内存中
包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象
确定一个值是哪种基本类型使用typeof(),确定值是哪种引用类型使用instanceof()

所有变量都存在于一个执行环境(作用域)中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。

执行环境有全局执行环境和函数执行环境之分;
每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其父环境,乃至全句环境中的变量;
全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
变量的执行环境有助于确定应该何时释放内存

JavaScript是自动进行垃圾回收的,开发人员不必关心内存分配和回收问题。
离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。
"标记清除"是目前主流的垃圾收集算法,思想就是给当前不使用的值加上标记,然后再回收其内存
"引用计数"的思想是跟踪记录所有值被引用的次数,JS引擎目前都不使用这种算法
在代码中循环引用时,"引用计数"算法会出现问题(内存泄漏)
解除变量引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象,全局对象属性及循环引用变量的引用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: