JavaScript高级程序开发3笔记

                                                                                                    Js对象

注意:js基本数据类型不是对象,但是“abc.match()这种,可以调用对象的方法,是因为调用方法是临时产生了一个wrapper的包装对象,this指向它;

 

 

Js对象属性的配置

 

Configurable:  构造,是否能够delate该属性,修改该属性特征

 

Enumerable:  该属性是否能够被枚举(如for in JSON.stringify转字符串)

 

Writable:  是否为只读

 

Value:   设置值

 

Object.defineProperty(obj,”key”,{

  

})

defineProperties是修改多个对象属性的方法。

Object.getOwnPropertyDescriptor(obj,”key”)返回该属性的描述符对象。

propertyIsEnumerable(propertyName):是否可枚举

 

只要设置了Configurablefalse,则这个属性无法改变配置,即无法再次用从configurable设置其表征 

 

原来在对象里声明以key-value 形式的属性,其默认的描述符都为true,而在Object.defineProperty中设置的不初始化都为falseconfigurablefalse的属性无法再次配置属性(会报错);

 

访问器属性:有且仅有四个属性。不初始化为false或者undefined

Object.defineProperty(obj,”year”,{

   Configurable:true,

Enumerable:true,

Set:function(){},

Get:funciton(){}

 

})

 

 

变量、作用域、内存问题

 

Typeofa==undefined

这有两种情况,1:未赋值,或者调用对象的属性(如var obj={}, obj.a;

              2:未定义,会报错。

   

 

JavaScript不能直接访问内存中的位置,也即是说不能直接操作对象的内存空间,操作对象时,实际上操作的是对象的引用而不是实际的对象。也就是说直接比如:var a={name:”tom”};

Var b=a; a=null; b不会被清空,是a这个指针被清空。

 

jQuery中复制对象的方法var b = $.extend(true, {}, a);

 

Js中求值策略:

但是请注意!!: js中基本类型,是按值传递,而对象,也就是引用类型并不是按引用传递,而是按共享传递(call by sharing),也就是说操作对象属性时,可以相互影响,而重置这个对象时,就相当于在堆中新建了一个对象,无法影响另一个引用。

变量类型:基本类型和引用类型;

基本类型(简单数据类型:直接把值存在栈内存中,值的大小是固定的)Undefinded  , Null  , Boolean , Number ,String

     复制给另一个变量过程是:直接复制    

      

 

引用类型(复杂数据类型:栈中对象在堆中的地址):对象的形式

  以构造函数声明的都为引用类型,如var a=new String(“abc”); 有内部属性,length:3 , 0:“a,1:”b” , 2:”c”

       赋值给另一个变量的过程是:赋予指针,指向堆中的对象

 

参数传递ECMAScript中所有函数的参数都是按值传递,即使是引用类型的变量类型,也是按值传递,意思是说:会把这个值在内存中的地址复制给arguments对象的一个元素,也就是在栈中复制了一个带有这个对象在堆中的地址,但是这个局部对象和外部的对象的引用是指向堆中同一个对象,因此在局部环境中修改这个对象的属性仍然对外部的对象有影响。

例子:var person={

name:"tom",

age:10

}

function kk(pn){

pn.age=11;

pn.sex="man";

Pn=new

}

kk(person)

console.log(person)

Person 并没有清空;

 

Type of :

  在检测基本类型是,这个方法非常好用(除了null会返回object);

但是当检测引用类型时候,就会返回objectfunction当想要知道它是什么类型的对象时候无用。

  正则比较特殊,Safari 5 和 chrome 7之前检测为 function

 

Instanceof:  person instanceof Object  true(当然只要是引用类型这会一直为true)  ...是否是..的实例

 

 

执行环境

含义:执行环境定义了变量或函数有权访问的其他数据。

  每个执行环境都有与之关联的变量对象(环境中定义的变量和函数都保存在这个对象中),我们编写的代码无法访问这个对象,但是解析器在处理数据会在后台使用它。

  在某个执行环境中的代码执行完毕,该环境被销毁。

 

  每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在函数执行完毕,栈将其环境环境弹出,把控制权返回给之前的执行环境。

变量对象的作用域链(scope chain:如果是函数,则将其活动对象作为变量对象,一开始只有一个arguments对象。

 

延长作用域链

  With:如 with(expresion){} expresion添加到变量对象的前端,在{}里可以访问到expresion的方法和属性;

 

Try{}catch(err){} :会创造一个新的变量对象(err对象)在变量对象的前端。

 

垃圾收集

垃圾收集器会按照固定的时间间隔或者代码执行中预定的收集时间周期性释放内存;

垃圾收集器会追踪变量是否无用,对不再有用的变量打上标记,以便将来释放其内存。

标记无用变量的策略通常有两种:

1标记清除(mark-and-sweep

   会给所有变量加上标记,然后他会去掉环境中的变量以及被环境中变量引用的变量,之后加上标记的变量就是应该清除的变量。

2.引用次数(reference counting IE采用两种方式并存

  跟踪每一个值被引用的次数,如果引用次数为0,则清除这个值。(但是循环引用将会导致引用次数永远不能为0,)

 

内存管理

JavaScript中有一个最主要的问题是分配给Web浏览器的可用内存数量通常比桌面程序少(处于安全方面的考虑,防止JavaScript的网页耗尽所有系统内存导致系统崩溃)

内存限制不仅影响给变量分配内存,同时会影响调用栈以及在一个线程中能够同时执行的语句数量。

 

  因此优化内存:执行中的代码最好只保存必要的数据,一旦数据不再使用,最好null清空(解除引用),而局部变量会在它们离开执行环境是自动被解除引用。

     解除引用的真正目的是让值脱离环境,以便垃圾收集器下次将其回收。

 

 

引用类型

Object

  对象自变量实际上不会调用Object构造函数,  

 

对象自带的方法

  toString()    valueOf()   toLocalString()   toSource()

 

 

 

Array  

     字面量也不调用构造函数

检测数组: ... Instanceof Array   这是只有一个全局执行环境有效运行,如果网页有多个框架,就存在两个以上不同版本的Array构造函数。

最保险的是ECMAScript5 Array.isArray();  (ie9)

当然Object.prototype.toString.apply(arr)---->[object Array]最好,兼容性最好,当然这只能对 对象检测,如果是简单数据,则会像对 对象那样处理

 

Push pop shift unshift splice sclice

 

迭代方法:(除了foreach都对原数组无影响)

判断

Every   每一项返回true,则最终返回true   IE8+

Some    有一个返回true,则最终返回true   IE9+

过滤   

Filter   返回true的组成数组       IE9+

处理

Foreach  无返回,处理结果组成数组  IE9+

Map  返回值组成数组               IE9+

 

 

EMACScript中新增:reduce(function(pre,cur,index,array){})  reduceRight()---> 第一次迭代发生在第二项,每一个返回的值都作为pre

 

Function

由于函数名相当于指针,所以没有重载,函数名相同就是一个函数

 

caller属性:表示调用当前函数的函数的引用。如果是全局中调用,则为null

 

属性length:形参个数

 

 

 

 

包装类型Boolean Number String

 

“abc”.subString(2)

内部实际等同于运行了

 Var s1=new String(“abc”);

s1.subString(2);

S1=null;

 

 

String方法

Trim()返回一个副本,而不是本身

slicestartend

Substring(start,end)  

Substr(start,num)

 

第一个参数为负数slicesubstr(负数+length),substring (负数转换为0

第二个参数为负数slice(负数+length),substringsbustr (负数转换为0

Substring()是不能以负数起始的

布尔类型的对象和数字类型的对象,重写了valueof--->true||10, tostring---->”true”||”10”

 

 

   indexOf(str,start)

 

   lastIndexOf(str,start)搜索方向从后向前

 

  tolowerCase()  toUperCase()

 

 

 

Match(pattern);      类比exec()非全局下返回一致,而全局下根据lastIndex搜索下一个匹配值,并返回新的lastIndex

 

Search(str||pattern);  returnposition||-1 

 

Replace(str||pattern, str)  return: 全局下返回所有匹配的字符串数组

  Replacestr”word($)”)

 

Replace(str||,function(match,pos,originalText){})

 

 

 

 

 

 

 

 

 

 

 

原型

 

任意一个函数都有一个内置的原型对象prototype,它里面内置有有两个属性__proto__ constructor,这个constructor指向这个函数。(当然,每个js对象都有__proto__对象,而不仅仅是函数)

 

注意:当使用如 a.prototype.name=”tom”是给原型对象添加属性,而a.prototype={}重置了prototype对象,__proto__ constructor被清空了。所以

function a(){}

a.prototype={name:"tom"};

var b=new a();

console.log(b.constructor)  //得到的是第二层原型链中的constructor

 

a.prototype===b.__proto__;

a.prototype.isPrototypeOf(b);

b.hasOwnProperty(“name”);

Object.getPrototypeOf(b);

Object.getOwnPropertyNames(a.prototype)   获取原型对象keys数组 等同于Object.keys(a.ptototype)   同时Object.keys(b)返回实例属性

 

 

New 运算符做的事情

1.初始化对象; var obj={};

2.Obj.__proto__ =a.prototype;

注意:也就是说比如var a =function(){a.prototype={}} ;  var b=new a(); b.__proto__为原来的,而后更改a.prototype{},因而b.__proto__a.prototype不相等,导致a.ptototype.isPrototypeOf(b)false

而写在外部,则不会有这个问题,但是仍然会出问题,b.constructor不对,所以可以在外部设置a.prototype.constructor=a;即可,但是这样一来,constructor就可以被枚举了,可以用Object.defineProperty()表示;

3.a.call(obj) :构造obj,初始化obj

 

In操作符

1.单独使用

   Alert(“name” in b); true -->这要是b的属性,都可以返回true

2.for in

 

实例和原型之间是松散链接,即是用指针指向原型;

 

原型对象的缺陷

  如果原型对象的属性中有应用类型,比如:

Var b.ptototype={

   People:[“jim”,”tom”]

}

这样修改一个实例的people属性,会影响所有的people属性。如果是重写,则无影响。

 

在构造函数中,一旦像工厂模式这样直接return一个对象,就会new调用构造函数时的值(这样构造出来的对象会被覆盖),但是如果直接return简单数据类型(null undefined/什么都不写 string number boolean),则不会对返回的实例对象有任何影响。

 

 

 

函数

函数声明

Function a(){}  --->a.name=a

函数表达式(实际上这种也会提升,但是没有赋值,也就是说变量对象在解析时,所有变量和函数都会被推入,但是变量都没有赋值)

Var a=function(){},匿名函数; name值为空

 

注意:无效语法 ifcondition{funtion a()}{}else{function b(){}}---->这会导致错误,大多浏览器会忽略condition,直接返回第二个声明,而ff表现正常

 

参数

arguments{}----->都是内部属性,010, 1:24 , 2:32 (可配置,可枚举,可写);length(可配置,不可枚举,可写) ; callee:对该函数的指针(可配置,不可枚举,可写)

 

Function a(num1,num2){}  a(1,2,3)

在函数内部argument[i] num1num2的值是相等的,但是它们访问的内存空间不是相同的,它们的内存空间是独立的,只是值同步。

注意:在非严格模式,arguments[i]和相对应的num的值是相互影响的,修改其中一个,另一个也会被修改,而严格模式,修改其中一个,另一个不受影响。同时严格模式不允许重写arguments对象(直接报错)。而非严格模式可以修改,但是num 不受影响。

 

函数指针

arguments.callee

 

没有重载:

由于没有函数签名(接收参数的类型和数量),所以没有重载。

 

属性:length  prototype call apply caller

 

 

 

    

 

 

 

 

递归函数

递归函数内部使用arguments.callee替代函数名更安全,它是一个指向当前函数的指针

----->当在外部改变该函数时候,如var other=diguifunction; diguifunction=null; 不会出错

 

 

闭包

罗列闭包情景

Function name(){
   return function(){}

}

 

 

Function a(){

Var arigin=arguments.callee;

This.gouzao=function(){

    Return arigin

}

}

 

 

 

 

 

闭包:指有权访问另一个函数作用域里的变量的函数

记住:当你想在当前的一个未运行的函数表达式是中输入变量(这个函数在以后你调用的时候可能这个变量已经被以前的操作给修改了,我可以管这叫即时输入变量的值),一定要使用一个闭包。

 

匿名函数

匿名函数的执行具有全局性:

所以在调用一个返回匿名函数的情况下,匿名函数中的this会指向window

 

 

This

var obj={

   a:function(){

     alert(this)

}

}

  (obj.a=obj.a)()------------>window  ,赋值语句,

    

 

    

 

 

 

执行优先级

 

     语句执行==前置递加,递减 >后置递加,递减

 

 前置递加,递减与语句执行优先级相等,因而以下合理

 var a=10;

 var b=a++;       

 alert(b);  // 10

类型转换

 

 

 

手动类型转换


1.value.toString() ------->不能转换null undefined ,而且对纯对象会转化为【object Object,对数字 num.toString(2)

2."" + value 

3.String(value)     对纯对象会转化为【object Object

4.JSON.stringify()    json对象进行转换 

 

5valueOf() ------->不能转换null undefined,返回数字,字符串,对象

6.Typeof

7.Number()

8.ParseInt()  parseFloat()  “12ab”---->12

 

强制类型转换

  1.对某个值进行计算时候(++--+,……)

      字符串转换(num NaN

       Boolean(0, 1)

       对象(先调用valueOf

 + 和  —放在前面,类型转换(—转负数,类型转换)

 

反码:

补码:反码+1

 

位操作符(直接对二进制按位进行操作):数值表示的最底层的操作,因而速度最快

    对NaNInfinity进行位操作,这两个都会作为0处理

按位非NOT :  ~  反码

按位与AND:  &  返回对其 的位上的都为1(或0)的返回1(0),其他为

按位或OR:    |   都为返回0

按位亦或XOR:  ^    有且仅有一个1,返回1

左移: num <<  5    向左移动5

右移(有符号位): num>>   5    向右移动5位(在符号位右边填充0

无符号位右移 :num>>> 5   在一开始填充0,对负数有影响

 

逻辑操作符 

  !   !!等同于Boolean()

 对 !{}false

  !””:true

  !”ab”:false

 !0:true

!NaN:true

!undefined:true

!null:true

!Infinity:false

 

&&------》(可以理解找false返回,找不到返回第二个)

  Var reslult=a && b;

a求值不为false是才返回bfalse时返回a

 

||----》(可以理解为找true返回,找不到返回第二个)

  Var result=a||b;

a求值不为true才返回batrue是返回a

 

+  中如果两个中有一个不是数字 那么:对象、数值、布尔值、Infinity先调用toString()undefined,nullString()特殊情况:数字+undefinedNaN ;  5+null5  ;数字+Infinity:Infinity

 

-  中如果有一个操作数为字符串、布尔值、null  undefined先调用Number()

如果有对象,则调用valueOf()

     Number(“120ab”)--->NaN;  即“120ab-10 :NaN

 

关系操作符

字符串比较:字符编码比较(比较首字母)”23”<”3” 是true

如果有一个数字,另一个要转化为数字

对象:valueOf()如果没有valueOf() 则用toStirng()

 

值相等(==)先转化再比较(两个对象比较时,仅有指针指向同一个对象时返回true)

特殊:nullundefined相等(虽然Number(

undefined):NaN  Number(null):0

 

全等(===)直接比较

   

逗号,一个语句中执行多个操作

Ifexpresion) Boolean(expresion)转换

 

 

语句

标签lable

   outermost:

        For(var i=0;i<12){

                For((var i=0;i<12;i++){

            continue outermost;           //continue 外层循环。

}

)

 

 

 

                          Global全局

 

escape 和 unescape()已经废弃

encodeURI  

对应decodeURI

 

encodeURIComponent():对任何它发现的非标准字符进行编码

对应 decodeURIConponent()

 

                        内存泄露

 

这种闭包,这样写,循环引用了,内部element内存无法释放。

 

如果程序中只需要引用dom上挂载的数据,可以直接把它提取出来,而不要直接写在事件函数里,因为这样事件对这个对象的引用不会消失,因而对象不会被回收。

 

模块模式

经常使用一个单例

 

事件

 

事件流

IE 的事件冒泡

Netscape Communicator的事件捕获

 

事件流的是三个阶段:

  事件捕获阶段(规范要求这个阶段不会接收到事件,但是)、处于目标阶段、事件冒泡阶段

          处于目标阶段实际上被看成冒泡阶段的一部分。

 

事件侦听器(事件处理程序)

       有权访问全局作用域的任何代码

 

直接在html元素中添加事件监听有几个缺陷:

1.不利于管理开发(紧耦合)

2.Html元素显示时可能事件未添加,引发错误(可以用try{}catch()屏蔽错误)

 

 

adEventListener(“docha”,function(){},false)  removeEverntListener(“docha”,function(){},false)

注意:参数中匿名函数这种形式无法取消绑定事件函数。所欲参数指向相同时才能取消,因而要用句柄的形式

 

 

事件对象

   属性方法:

Bubbles       是否冒泡  

Cancelable       是否可以取消事件默认行为

 

Current Target      事件处理程序当前正在处理事件的元素

Target              事件的目标

Trusted               浏览器生成为true,开发人员通过JavaScript创建为false

Type               事件类型

View              与事件相关联的抽象视图

Default Prevented           是否已经调用了 Prevent Default()

Detail               事件相关的详细细节

Event Phase          1:事件捕获  2:处于目标 3:冒泡阶段

Prevent Default()       取消系统默认行为

stoImmediateProipagation()  取消事件捕获或冒泡,同时阻止程序被调用

stopPropagation()         取消捕获或冒泡

 

创建事件对象监听:

IE8attachEvent()

现代:addEventListener()

 

创建自定义事件:

   

IE8

  1.创建事件对象:var event=crateEventObject();

   2.添加属性: event.msg=”我是fierEvent触发的

   2.触发事件  obj.fireEvent(“onclick”,event)

   

现代: 

   1.创建事件对象:var event=createEvent()

2.初始化事件对象:event.initEvent()

3.分配事件对象:obj.dispatchEvent(event)

 

 

主动触发objDom.dispathEvent()

 创建事件对象   Var evt=document.createEvent(“Event”);

 初始化对象evt.initEvent(“click”,true,true) 三个参数的含义eventType,canBubble,cancelable

分配事件对象  objDom.dispatchEvent()

兼容性解决方案

var dispatch = window.addEventListener ? 
function(el, type){ 
try{ 
var evt = document.createEvent('Event'); 
evt.initEvent(type,true,true); 
el.dispatchEvent(evt); 
}catch(e){alert(e)}; 
} : 
function(el, type){ 
try{ 
el.fireEvent('on'+type); 
}catch(e){alert(e)} 
};

Dispatch(objDom,”click”);

 

DOM

cloneNode(true)---true:是否复制属性

 

 

 

 

 

补充

 

 

具名函数

Var a=funciton b(){}         //具名函数

IE8以上以及其他浏览器无法在外部访问到b(会报错),只能在内部访问到b

 

Var a=function(){}           //匿名函数

 

posted @ 2016-11-21 20:59  唯物主义开发者  阅读(436)  评论(0)    收藏  举报