JavaScript

《JavaScript设计模式与开发实践》

JavaScript的根对象是Object.prototype对象——一个空对象,JS中每个对象都来自它的克隆,Object.prototype就是它们的原型对象,所有对象都可追溯到它

通过克隆Object.prototype来得到新的对象

function Person(name){

this.name= name;

}

var a = new Person(‘sven’);

JS没有类,new Person这里是函数构造器,JS的函数可做普通函数被调用,也可做构造器被调用

1.1、JavaScript中的原型继承

javascript中没有类,遵从原型编程的基本规则

1、数据都是对象 2、对象是通过找到另一个对象作为原型并克隆它

3、对象会记住它的原型

准确来说对象没有原型,而是构造器有原型,说的是构造器的原型

4、如果对象无法响应某个请求,它会把这个请求委托给它自己的构造器原型

对象有隐藏属性-proto- 默认指向它的构造器的原型对象。

四、运算符
!==可以区分null、undefined

五、语句
for/in循环可以遍历对象中所有可枚举的属性(包括自有属性和继承属性),对象继承的内置方法不可枚举

六、对象
对象(数组、函数)

除了不可变的原始值外(字符串、数字、布尔、null、undefined)外,JS中的值都是对象,字符串、数字、布尔值行为和不可变对象非常类似

JS为方便描述,人为划分三类对象和两类属性
内置对象:由ECMScript规范定义的对象或类,数组、函数、日期、正则表达式都是内置对象

宿主对象:由JS解释器所嵌入的宿主环境(比如web浏览器)定义的。客户端js中表示网页结构的HTMLElement对象均是宿主对象。既然宿主环境定义的方法可以当做普通的Js函数对象,那么宿主对象也可以当成内置对象。

自定义对象:在运行中创建的JS对象

own property:直接在对象中定义的属性

inherited property :对象的原型对象中定义的属性

6.1创建对象
方式:对象直接量、new、Object.create()函数

6.1.1原型

Object为Object也代表具体对象

Object.prototype获得原型对象引用,例如:通过new Array()创建的对象原型为Array.prototype

[注]没有原型的对象不多,其中Object.prototype没有原型对象

6.1.2、Object.create通过任意原型创建对象

Object.create(),创建一个新对象,param1——是这个对象的原型,param2——对这个对象的属性描述

var o1 = Object.create({x:1,y:2}); //o1继承了x,y

如何创建空对象

var 02 = Object.create(Object.prototype)、new Object、{}

6.1.3 作为关联数组的对象

object.property==object[“property”],后者更像数组,这个数组元素是通过字符串而不是数字访问。这种数组就是关联数组,JS对象都是关联数组,也叫散列、映射、字典。

6.14检测属性

in、hasOwnPreperty()、propertyIsEnumerable()

in —检测自有和继承属性

hasOwnPreperty–检测自有

propertyIsEnumerable----检测自有且可枚举

6.2

Object.keys()、Object.getOwnPropertyName()方法

6.3 属性:名字、值、attribute组成。

数据属性4特性:value\writable\enumrealbe\configurable

存取器属性4特性:get\set\enumrealbe、configurable

[主要概念]1、getter\setter2、存取性属性3、定义对象O的存取器属性accessor_prop

定义:

var o = {

data_prop : value,

get accessor_prop(){函数体},

set accessor_prop(value){函数体}

}

6.3.1”属性描述符“对象
用来代表4特性,该对象的属性和它们所描述的属性特性同名。

Object.getOwnPropertyDescriptor()可以获得对象的属性描述符。

Object.definedProperty(),用来创建或修改属性以及描述符对象

Object.definedProperties(),

6.4对象三属性
每一个对象都有三属性:prototype,class,extensible attribute

[使用]

6.4.1prototype属性

Object.getPrototypeOf(o),可查o的原型,

检测一个对象是否是另一个对象的原型(或处于原型链)------isProtorypeOf()

6.4.2class属性

是一个字符串

只有间接方法查询到它 toString()方法(继承自Object.prototype) 返回[object class] 再提取第8个到倒数第二个之间的字符

不过很多对象重写了toString(),为了正确得到toString()版本必须间接调用Function.call()方法

【注】通过对象直接量和Object.creat(),和自定义构造函数创建的对象的类属性是"Object"

内置构造函数与名字匹配

6.4.3 extensible:目的是“锁定”,避免外界干扰

对象的可扩展性用于表示是否可以给对象添加新属性。内置对象和自定义对象都是显示可扩展,宿主对象的可扩展性是由JS引擎定义的。

使用:

Object.esExtensible§:用来判断p是否可扩展

Object.preventExtensions():对象————————》不可扩展,一旦对象转换为不可扩展就不可逆。

Object.seal(),Object.isSealed(),

Object.freeze(),Object.Isfrozen().

说明:preventExtensions、seal、freeze都返回传入的对象,也就是说可以通过函数嵌套的方式调用它们

var o = Object.seal(Object.creat(Object.freeze({x:1}),{y:{value:2,writable:true}}));

6.5序列化对象
对象序列化是指将对象的状态转换为字符串,也可将字符串还原为对象

ECSScript5 提供内置对象JSON.stringify() 和JSON…parse()用来序列化和还原JS对象。

【特别说明】stringify只能序列化对象的可枚举的自有属性。两者都接受第二参数来定制操作

JSON 是JS语法的子集,并不能表示JS里面所有的值,

支持:对象、数组、字符串、无穷大数组、布尔、null

特殊:NaN、Infinity、-Infinity 序列化结果为 null

特殊:Date对象的序列化结果为 ISO格式的日期字符串(参照Date.toJSON()函数),但JSON.parse()依然保留字符串格式,不会转为Date对象

不支持:函数、RegExp,Error对象、undefunded。

6.6对象方法(Object.prototype)
6.6.1toString()

返回:一个表示调用这个方法的对象值得字符串

什么时候调用:在需要将对象转为字符串的时候。

由于默认toString()返回信息太少,很多类都有自定义toString()方法

6.6.2 toLacalString()

返回:表示这个对象的本地化字符串

Object中默认的toLacalString只是调用toString,Date、Number类对toLacalString做了定制,可以用它对数字、日期做本地化转化,Array.toLacalString()是调用每个数组元素的toLacalString

6.6.3 toJSON()

object.prototype,没有此方法,对于需要序列化的对象来说,JSION.stringify()会调用toJSON()方法,如果待序列化的对象存在该方法,则调用它

6.6.4 valueOf()

什么时候用:需要将对象转为原始值而非字符串时候,尤其转为数字的时候。

有些类自定义了valueOf,比如Date.valueOf();

七、数组(2^32-2)
数组继承Array.prototype中的属性,它定义了一套丰富的数组操作方法。

【数组索引本质】数组是对象的特殊形式,适用方括号访问数组元素就像用方括号访问对象的属性一样。JS将指定的数字索引转换为字符串,然后将其作为属性名使用。故数组本质上其索引也是属性值。

索引特点:可以负数或非整数来索引数组,数字转为字符串,字符串作为属性名

例:a[-1.23] = true;a[23.4]=a;

创建:直接量、构造函数new Arrray().

当使用小于2^32的非负整数 ,Array自动更新length值。

7.1 数组元素的添加和删除

添加:索引、push()、unshift()

删除:delete、pop()、shift()

通用方法 :splice()

遍历的新方法:forEach()

7.2 数组方法

7.2.1 join()—将数组元素拼接在一起

reverse()-----反转元素

sort() 排序,可接受排序规则函数

concat()—创建并返回新数组

slice()—返回数组片段

splice()—插入或删除元素,或同时进行两种操作,返回由删除元素组成的数组。

splice(i,j,…)-------i、j定义删除的元素,i以及之后元素定义插入元素

splice(1)删除1以及之后所有元素,

splice(1,2),删除1以及以后2个元素

splice(1,0,[2,3],6);

push()、pop() 返回长度

unshift()、shift()返回元素

7.2.2 ECMScript5 定义的数组方法

foreach(),调用函数传入一个参数,代表value,传入三个参数代表,value,索引,数组。

如果只关心数组元素值可以编写只有一个参数的函数

map()调用数组的每个元素传递给指定函数,该函数应该有返回值,返回的数组包含所有返回值。

filter()返回数组子集,传入函数是用来逻辑判定的,返回值是true或false

every()、some() 是数组的逻辑判定,它们对数组元素用指定函数进行判定,返回true或false

reduce()|reduceRight() 使用指定函数将数组元素进行组合,生成单个值。区别是从左到右和从右到左

indexOf()、lastIndexOf()搜索整个数组具有给定值的元素,接受两个参数(v,j)j可选,表示偏移量

7.3数组类型

思考:除了isArray()方法还能怎样区分数组和非数组

数组类型判定:Array.isArray()

7.4类数组对象

思考:数组对象有哪些特性,普通对象没有的。

定义:把拥有一个数值length属性和对应非负整数属性的对象看做一种类型的数组

var a = {“0”:“a”,“1”,“b”,“2”:“c”,length:3}

7.5 字符串另一个身份——作为只读数组

数组的不改变值的一些操作方法适用于字符串

八、函数
this关键字:

任何函数只要作为方法调用实际上都会传入一个隐形实参对象this----这个对象就是方法调用的母体。

rect.setSize(width,height);

setRectSize(rect,wight,height);

假定两行代码功能完全相同,他们都作用于一个假定的rect对象,而第一行简明清晰表明了函数执行的载体是rect对象,函数中所有的操作都将基于这个对象。

JavaScript中函数也是对象,是特殊对象,可以定义变量和函数属性(即函数多重嵌套函数)

8.1 函数定义

两种方式:表达式,语句

【定义后立马使用】()为运算符,(function)为立马使用函数

1、var a = function(a){ console.log(a)} 定义

2、(function(a){ console.log(a)}(success) ) 定义后立马使用,只是用一次的可以这样定义为匿名函数

8.2 函数调用

4种方式:作为自身独立的函数;对象方法;构造函数;通过call()和apply()

【注意】t和变量不同,this没有作用域的限制,嵌套函数作为方法调用,其this值就指向调用它的对象,作为函数调用,其this值不是全局对象(非严格模式)就是undefined(严格模式)

8.3 间接调用

函数作为对象也包含call()和apply()方法,两个方法可以间接调用函数。

两个方法都允许显示指定调用所需的this值,也就是说,任何函数都可以作为任何对象的方法来调用。都可以指定实参,call()使用自有的实参列表作为函数的实参,apply()要以数组的形式传入参数

8.4 实参对象

8.4.1 arguments 指向实参对象

8.4.2 callee、caller 属性

callee属性指代当前正在执行的函数,caller指代调用正在执行函数的函数

用处例如:callee属性 实现递归

var factotial = function(x){ if(x<=1) return 1; return x*arguments.callee(x-1)}

8.4.3 传入整个对象------将对象属性作为实参

8.4 函数也是值

函数不仅仅是语法,也是值,可以将函数赋值给变量,存储在对象属性或数组元素中,作为参数传入另一个函数等

8.5 闭包

作用域、作用域链

闭包概念:函数对象可以通过作用域链关联起来,函数体内部的变量都可以保存在函数作用域内的特性叫做闭包。闭包是一种特性。

8.6 函数的属性,方法和构造函数

两个属性,两个方法

length属性:arguments.length代表实参个数,length代表函数的定义时候的形参个数

propertyprototype属性:指向一个原型对象的引用

借鸡生蛋,call()方法,和apply()方法【可以方便实现,函数的四处调用,即使不是该对象方法,也可以由该对象调用】

call(o,arguments),第一个参数都是传入上下文对象,不同的是,call传入有限个实参,apply()需要传入数组。

bind()方法 ,将函数绑定至对象

toString()方法

Function()构造函数,相当于eval(),万万切记,Function构造函数编译只能看到全局属性,函数内属性无法访问

8.7 函数式编程

JS不是函数式编程语言,但可以像操作对象一样操控函数,也就是说可以在JS中应用函数式编程技术。请看下面的应用

8.7.1 使用函数处理数组

8.7.2 高阶函数

高阶函数就是操纵函数的函数,他接收多个函数作为参数并返回一个新函数

8.7.3 不完全函数,不完全调用(一种函数变换技巧,把一次完整的函数调用拆成多次调用,每次调用都返回一个函数)

例如:f(1,2,3,4)拆成f(1,2)(3,4)

8.7.4 记忆

一种编程技巧,在函数式编程中把上次计算结果缓存起来,本质就是空间换时间

九、类和原型

1、类、原型、构造函数:原型对象是类的唯一标识,任何js函数都可以作为构造函数,每个js函数都自动拥有一个prototype属性,这个属性值是一个对象,这个对象包含一个不可枚举属性constructor。constructor属性的值是一个函数对象。

当指定Range.prototype原型,对Range()构造函数的调用会自动使用Range.prototype作为新Range对象的原型。

2、constructor属性:就是一个函数对象

3.JS中的Java式的类继承

4、类的扩充

可以通过给原型对象增加方法扩充JS类

JS内置类的原型对象也是“开放的”,可以给数字,字符串、数组、函数等数据类型添加方法

5、类和类型

提问:对于"基本类型",检测其类型可以用typeof,但是对于类如何区分(如何让类告诉你它的名字)?

检测对象类的技术:instanceof运算符,constructor属性,构造函数名字。

instanceof或者isPrototypeOf,无法让类说出它的名字。

constructor识别对象属于某个类(它说出了名字)。

构造函数名称。

6、JS中的面向对象的技术

方法借用:

JS中的“多重继承”通过“方法借用来实现”,即多个类中的方法共用一个单独函数,

私有状态----------类比 private

实现:将变量(或参数)闭包在一个构造函数内来模拟实现私有字段。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值