js自学笔记—— 基础部分一

前言: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
  1. 浮点数值

由于保存浮点数值需要的存储空间是整数值的两倍,所以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引擎目前都不使用这种算法
  • 在代码中循环引用时,"引用计数"算法会出现问题(内存泄漏)
  • 解除变量引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象,全局对象属性及循环引用变量的引用。
时间: 2024-10-25 18:33:55

js自学笔记—— 基础部分一的相关文章

js自学笔记---基础部分二

前言:引用类型的值(对象)是引用类型的一个实例.引用类型是一种数据结构,用于将数据和功能组织在一起.有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法. 1.引用数据类型 Object类型 var person = new Object();//通过object的构造函数去创建对象 var person = { //通过对象字面量表示法创建 name:"张三", "age":23, 5:true //数值属性名5会自动转成字符串 }; var per

Linux自学笔记--基础命令date,cal等

逆水行舟,不进则退: date命令: 我们可以来man一下date命令,可以在上面看出 date的含义为 - print or set the system date and time,我们从以下几方面对date命令进行阐述. 1.   显示时间 date[OPTION]... [+FORMAT] format:格式符号 %D: %F: %T: 在屏幕中输入单独的date命令可以显示系统的时间: 同时我们也可以显示自己想要的时间显示格式: 2.   设置时间 date[-u|--utc|--un

js自学笔记(1)

1.false == 0; // true false === 0; // false 要特别注意相等运算符==.JavaScript在设计时,有两种比较运算符: 第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果: 第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较. 由于JavaScript这个设计缺陷,不要使用==比较,始终坚持使用===比较. 2. JavaScript在设计之初,为了方便初学者学习,并不强制要求用v

js自学笔记--面向对象

前言:ECMA-262将对象定义为:"无序属性的集合,其属性可以包含基本值,对象或者函数".这就相当于说对象是一组没有特定顺序的值.对象的每个属性或方法都有一个名字,而每个名字都映射到一个值.正因为这样,我们可以把ECMAScript的对象看成散列表:一组名值对,值可以是数据或函数.(每个对象都是基于一个引用类型创建的) 对象理解 1.属性类型 ECMAScript中有两种属性:数据属性和访问器属性. 1.数据属性 数据属性包含一个数据值的位置,在这个位置可以读取和写入值.数据属性有4

Node.js学习笔记【3】NodeJS基础、代码的组织和部署、文件操作、网络操作、进程管理、异步编程

一.表 学生表 CREATE TABLE `t_student` ( `stuNum` int(11) NOT NULL auto_increment, `stuName` varchar(20) default NULL, `birthday` date default NULL, PRIMARY KEY  (`stuNum`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 学生分数表 CREATE TABLE `t_stu_score` ( `id` int(11

JS学习笔记-OO疑问之封装

封装是面向对象的基础,今天所要学习的匿名函数与闭包就是为了实现JS的面向对象封装.封装实现.封装变量,提高数据.系统安全性,封装正是面向对象的基础. 匿名函数 即没有名字的函数,其创建方式为 function(){...} 单独存在的匿名函数,无法运行,可通过赋值给变量调用或通过表达式自我执行来实现运行. 1.赋值给变量为一般的函数使用方式 var run = function(){ return '方法运行中'; }; alert(run()); 2.通过表达式自我执行 (function(a

jQuery:自学笔记(5)——Ajax

jQuery:自学笔记(5)--Ajax 使用Ajax快捷函数 说明 出于简化AJAX开发工作的流程,jQuery提供了若干了快捷函数. 实例 1.显示 test.php 返回值(HTML 或 XML,取决于返回值). $.get("test.php", function(data){   alert("Data Loaded: " + data); }); 2.向页面 test.php 发送数据,并输出结果(HTML 或 XML,取决于所返回的内容): $.pos

python自学笔记(一)

我没学过python,通过网上和一些图书资料,自学并且记下笔记. 很多细节留作以后自己做项目时再研究,这样能更高效一些. python基础自学笔记 一.基本输入和输出 pthon3.0用input提示用户输入,用print提示用户输出,格式为print("...") 如果格式化输出,那么格式为print("%d" %(变量名)), %d可以替换为%s等其他格式符, 以后用到什么格式自己查,这样学起来高效. 简单的例子: #-*-coding:utf-8-*- nam

Node.js学习笔记【1】入门(服务器JS、函数式编程、阻塞与非阻塞、回调、事件、内部和外部模块)

笔记来自<Node入门>@2011 Manuel Kiessling JavaScript与Node.js Node.js事实上既是一个运行时环境,同时又是一个库. 使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器. 一个基础的HTTP服务器 server.js:一个可以工作的HTTP服务器 var http = require("http"); http.createServer(function(request, response) { r