Javascript高级程序设计笔记

第一章 Javascript简介

Javascript实现

  • 核心(ECMAScript)
  • 文档对象模型(DOM)
  • 浏览器对象模型(BOM)

ECMA-262

  • 语法
  • 类型
  • 语句
  • 关键字
  • 保留字
  • 操作符
  • 对象

文档对象模型

针对XML但经过扩展用于HTML的应用程序变成接口API。把整个页面映射为一个多层节点结构。提供访问和操作网页的方法和接口。

  • DOM1映射文档结构
  • DOM2
  • DOM视图(Vidws)
  • DOM事件(Events)
  • DOM样式(Style)
  • DOM遍历和范围(Traversal and Range)
  • DOM3加载文档的方法、验证文档的方法

浏览器对象模型

提供与浏览器交互的方法和接口。

第二章 在HTML中使用JavaScript

引入外部javascript, 标签之间不能再添加额外的内容。否则不执行。


defer属性,脚本延迟到整个页面解析完再执行。每个标签按顺序执行。
async属性,不能保证按先后顺序执行。
charset属性,字符集。

script内嵌文件中出现的内容要\转义。

外部文件的优点:

  • 可维护
  • 可缓存
  • 适应未来

noscript元素
当浏览器不支持JavaScript的时候,显示noscript元素中的内容。“需要启用JavaScript”

所有script元素都会按照他们做页面中出现的先后顺序依次被解析。在不使用defer和async的情况下,只有在解析完前面script元素中的代码之后,才会开始解析后面script中的代码。一般放在文档的后面 。
使用defer属性可以 让脚本在文档完全呈现之后再执行,延迟脚本总是按照指定他们的顺序执行。
使用async属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。

第三章 基本概念

语法

  • 区分大小写
  • 标识符:第一个字符必须是字母、下划线、美元符号,其他字符可以是字母、下划线、美元符号、数字。可以包含ASCII和Unicode字符,驼峰大小写格式。
  • 注释 // 单行注释 /****多行注释****/
  • 严格模式:不确定的行为得到处理,不安全的行为抛出错误,"use strict" 可以在顶部添加代码,也可以在指定函数下添加。
  • 语句:结尾分号不是必须,但推荐使用。控制语句多行使用代码块,建议始终使用。

关键字和保留字

不一一列举了。

变量

松散型变量可以保存任何数据
var message; //undefined
var message="hi";
如果在函数中var定义一个变量,退出函数后会销毁。如果函数中不用var直接使用,全局变量退出后还能使用。
可以用逗号创建多个变量var message=1 , go="haha", age=29;

数据类型

基本数据类型 undefined,Null,Bollean,Number,String
复杂数据类型 Object

typeof操作符

  • undefined 未定义
  • boolean 布尔值
  • string 字符串
  • number 数值
  • object 对象或者null
  • function 函数

instanceof检测对象

person instanceof Array

undefined类型

声明变量但是没有初始化。没有必要显式的声明。
var message;
alert(message); //undefined
alert(age); //产生错误

但是他们typeof都能输出undefined。

Null类型

空对象类型 typeof 返回object
未来使用空变量,初始化为null。
null == undefined //ture

Boolean 类型

在使用if的时候用于默认条件判断。 使用Boolean()进行转换
|数据类型|转换为true的值|转换为false的值|
|-|-|
|Boolean|true|false|
|String|非空字符串|空字符串|
|Number|非零数字包括无穷大|0和NaN|
|Object|任何对象|null|
|Undefined|不使用|undefined|

Number类型

八进制第一位是0,如果字面值中数值超出范围。那么前导0忽略。八进制在严格模式无效。
十进制前两位是0x。在进行算数计算时,所有的十六进制和八进制被转换为十进制。
isFinite(123) 判断是否无限大
没有小数部分的浮点数,会转换为整数。
1.2e7
1.2e-7
浮点数表示法

最大能表示的数值 Number.MAX_VALUE
最小能表示的数值 Number.MIN_VALUE
0除以0返回NaN,NaN和任何数值都不相等,包括本身。使用isNaN(123)--false,isNaN(NaN)当然返回true,不能转换为数值的,也会返回true。isNaN("10")就是false,isNaN(true) 可以被转换成数值1,也是false。isNaN("blue")不能转换成数值,是false。

Number()数值转换规则

  • 布尔值,转换为0和1
  • 数字,简单传入返回
  • null,返回0
  • undefined,返回NaN
  • 字符串,遵循以下规则。
  • 如果只含数字,转换为十进制数字,前导0忽略
  • 如果含浮点格式,转换为浮点数值
  • 如果包含有效的十六进制字符,转换成十进制数字
  • 如果字符串是空的,转换为0
  • 除上述之外,转换为NaN
  • 如果是对象,调用valueOf()方法,依照前面的规则返回的数值进行返回。如果结果是NaN,则调用对象的toString()方法,再依照前面进行返回。

parseInt()函数
找到第一个非空字符进行转换,如果第一个字符不是数字,返回NaN。因此,转换空字符串会返回NaN。而Number会返回0.第二个参数可以是基数。"22.5"返回22,小数点不是有效的数字字符。

parseFloat 函数
从第一个字符开始解析每个字符。一直解析到字符串末尾。或者解析遇见一个无效的浮点数字字符为止。第二个小数点无效。

String类型

字符字面量
\n \t \r
每个字面量长度是1
字符串不可变,要改变字符串,只能销毁原来的。
toString()方法
返回字符字面量,能传递基数,但是null和undefined没有这个方法。如果想把null和undefined转换成字符串,使用String()转型函数、

Object类型

var o = new Object()
每个实例都有下列属性和方法

  • constructor 创建当前对象的函数
  • hasOwnProperty 检查给定的属性在当前对象实例中是否存在
  • isPrototypeOf 检查传入对象是否是传入对象的原型
  • propertyIsEnumerable 检查给定对象能否使用for in语句
  • toLocaleString() 返回对象字符串表示,与执行环境对应
  • toString() 返回对象字符串表示
  • valueOf() 返回对象字符串,数值,布尔值表示

操作符

一元操作符

递增和递减操作符,前置和后置。

  • 包含有效数字字符的字符串,转换为数字后操作。
  • 不包含有效数字的字符串,变量设置为NaN
  • 布尔值转换为0和1再操作。
  • 浮点数,执行加减1
  • 对于对象,先调用valueOf方法,运用转换规则。如果结果是NaN,则调用toString()方法。

一元加减操作符。如果是非数值,用Number()转换,如果是对象,先调用valueof和toString方法,然后再转换。

位操作符

负数是二进制的补码,补码是反码+1.
按位非NOT 负值减1
按位与AND &
按位或OR |
按位异或 XOR ^ 相同为0 不同为1
左移 << 用0填充
右移 >> 用0填充

布尔操作符

逻辑非!
对象返回false,
空字符串返回true,
非空字符串返回false,
操作数0返回true,
非零返回false,
null返回true,
NaN返回true,
undefined返回true。
两个逻辑非,可以转换为布尔值。和Boolean() 相同

逻辑与&&

  • 第一个操作数是对象,返回第二个操作数
  • 第二个操作数是对象,只有在第一个求值结果是true情况下才返回该对象。
  • 两个操作数都是对象,返回第二个操作数。
  • 有一个操作数是null、NaN、undefined,则返回他
  • 短路操作

逻辑或||

  • 如果第一个操作数是对象,返回第一个操作数
  • 如果第一个操作数的求值结果为false,则返回第二个操作数。
  • 如果两个操作数都是对象,则返回第一个操作数
  • 如果两个都是null、NaN、undefined。
  • 短路操作

乘性操作符

乘法*

  • 如果操作符都是数值,按照常规乘法计算,超出范围变成无穷大。
  • 有一个操作数是NaN,结果是NaN
  • Infinity与0相乘,结果是NaN
  • infinity与非0相乘,结果是infinity或者-infinity
  • 两个Infinity相乘,返回Infinity
  • 有一个操作数不是数值,调用Number()转换后,在执行上面的操作。

除法/

  • 超过范围,结果是infinity或者-infinity
  • 有一个操作符是NaN,返回NaN
  • infinity除以infinity,返回NaN
  • 0除以0,返回NaN
  • 非零有限数被0除,结果是infinit或-Infinity
  • 有一个操作数不是数值,后台调用Number()转换后,再用上面的规则。

求模%

  • 数值返回正常值。
  • 被除数无限大除数有限大,返回NaN
  • 被除数有限大除数是0,返回NaN
  • Infinity被Infinity除,结果是NaN
  • 被除数有限大,除数无穷大,结果是被除数。
  • 被除数是0,结果是0.
  • 有一个操作数不是数值,调用Number(),再应用上述规则。

加性操作符

加法

  • 有一个操作符是NaN,结果就是NaN
  • 两个正无穷相加或者两个负无穷相加,结果就是正无穷和负无穷。
  • 正无穷和负无穷相加,结果是NaN
  • 字符串相加,就拼接
  • 一个是字符串,则将另一个转换为字符串,再拼接。
  • 如果操作数是对象、数值、布尔值,调用他们的toString()取得相应字符串的数值,对于undefined和null,分别调用string()取得字符串undefined和null

减法

  • 两个操作符都是数值,执行常规计算。
  • 有一个是NaN,结果都是NaN
  • Infinity-Infinity=NaN
  • -Infinity- -infinity = NaN
  • infinity--infinity=infinity
  • -infinity-infinity=-infinity
  • 0-0=0
  • 0--0=-0
  • -0--0=+0
  • 如果一个操作数是字符串、布尔值、null、undefined,后台调用number()将转换为数值,再根据前面的规则执行减法计算。如果转换的结果是NaN,那么整个结果是NaN
  • 如果有一个操作符是对象,调用valueOf取得对象的数值,如果得到的是NaN,则结果是NaN,如果没有valueOf方法,则调用toString()方法并得到字符串转换为数值。

关系操作符

  • 两个操作符都是数值,执行数值比较。
  • 都是字符串,比较编码数值
  • 如果一个操作数是数值,则将另一个操作数转换为一个数值进行比较。
  • 如果一个操作数是对象,则调用这个对象的valueOf方法,用结果进行比较。如果没有,就调用toString方法。
  • 如果一个操作数是布尔值,则现将其转换为数值,进行比较。
  • 任何操作符和NaN比较,都是false。

相等操作符

相等和不相等 先转换再比较

  • 有一个操作数是布尔值,转为数值再比较。
  • 一个是字符串,另一个是数值,比较相等这钱先将字符串转换为数值。
  • 一个是对象另一个不是,调用valueOf方法,用得到的基本类型和前面的比较。
  • null和undefined相等。不能将null和undefined转换为其他任何数值。
  • 有一个操作数是NaN,相等操作符返回false,不相等返回true。NaN不等于NaN。
    NaN<3 false
    NaN>=3 false
  • 两个操作数是对象,比较是否是同一个对象。

全等和不全等 仅比较不转换

条件操作符

variable = bollean_expression ? true_value : false_value;

赋值操作符

= += -= *= /= %= <<= >>= >>>=

逗号操作符

var num1=1,num2=2,num3=3;
var num=(2,4,5,6,7) //返回最后一个

语句

if语句

if(a>b){
    alert("aaa");
}else if(i<0){
    alert("aaa");
}else{
    alert("aaa");
}

if (condition) statement1 else statement2

do-while语句

do{
    statement
}while(expression);

while语句

while(expression) statement

for语句

for (initialization; expression; post-loop-expression) statement
for (;;;) statement 无限循环

for-in 语句
枚举对象属性,确认对象是不是或者undefined

for (property in expression) statement

label语句

label:statement

break和continue语句
可以返回标签

with语句

with(expression) statement
with(location){
    var qs =  qs
    var hostname = hostname
}
var qs = location.qs
var hostname = location.qs

switch语句 每句要break

switch(i){
    case 25:
        alert("25");
        break;
    case 35:
        alert("35");
        break;
    default:
        alert("other");
}

如果不写break,就会合并2个的情况。

函数


function functionName(arg0,arg1,...,argN){
    statements
}

return语句停止并立即退出,之后的语句不会执行。

ECMAScript函数不介意传递进来多少个参数,也不建议是什么数据类型。
arguments[0]可以获取第一个参数,并且时时保持同步。arguments.length确定传递进来多少参数。可以重写argument对应的值。如果没有赋值,那就是undefined。

没有重载

后面的函数覆盖前面的

第四章 变量、作用域和内存问题

基本类型和引用类型

动态属性

var person = new Object();
person.name = "abc";
alert(person.name); //"abc"

var name ="abc";
name.age =24;
alert(name.age); //undefied

不能给基本类型的数值添加属性。

复制变量值

基本类型的数值复制,两个变量相互独立。
引用类型对象复制,复制的为指针。

传递参数

所有函数的参数传递是按照数值传递。

function setName(obj){
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}

var person = new Object();
setName(person);
alert(person.name)   //"Nicholas"

内部的obj被赋予了其他的指针。

检测类型

基本类型使用 typeof
引用类型 result = variable instanceof constructor

执行环境及作用域

在web浏览器中,全局执行环境是windows对象。
代码在环境中执行,会创建变量对象的作用域链。
内部环境可以通过作用域链访问外部环境,但是外部环境不能访问内部环境中的变量和函数。

延长作用域链

try-catch语句的catch块
with语句
这两个语句都会在作用域链前端添加一个变量对象。对于with语句来说,会将指定的对象添加到作用域链中。对catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的生命。

没有块级作用域

在括号内的if或者for的变量是全局变量,不是局部变量。
在函数内,var是局部,不添加var是全局
查询标识符,由内部到外部。找到这个变量。

垃圾收集

以后再说标记清除、引用计数、性能问题、管理内存

第五章引用类型

Object 类型

创建对象

var person = new Object()
//对象字面量表示法
var person = {
    name:"aaa";
    age:29
}
var person = {
    "name":"aaa";
    "age":29
}
//对象最后不能加逗号
var a = {} //与new Object()相同

访问属性

person['name'] //可以用空格非数字,变量,关键字
person.name

Array 类型

var colors = new Array()
var colors = new Array(20) //预先知道长度
var colors = new Array("a","b","c") 
var colors = Array(3) //3项 
var colors = Array("aa")
var colors = Array(3) // 省略new 操作
var names = ['a','b'] //字面量法,
var names = [1,2,] //不要这样
var names = [,,,] //也不要这样
colors[0] //显示第0项,也可以修改,或者对新的项新增。
colors.length  //显示长度
colors[colors.length] = "a" //添加新项

value instanceof Array 检测数组,一个环境
Array.isArray(value) 确定到底是不是数组,不管哪个环境

转换方法

array.valueof() 返回数组,对每一项toString
toLocaleString()
toString() 返回数组每个值的字符串形式拼接而成的一个以逗号分隔的字符串
array.join("|")

栈方法

后进先出LIFO(last in first out)
array.push(1,2,3) 返回修改后数组长度
array.pop() 返回移除的数组

队列方法

先进先出FIFO(first-in-first-out)
array.push(1,2,3)
array.shift()

前进后出
array.pop()
array.unshift

重新排列方法

array.reverse() 反序
array.sort(function compare(value1,value2){return value2-value1})

function compare(value1,value2){
    if(value1 < value2){
        return -1;
    }   else if (value1 > alue2){
        return 1;
    }   else    {
        return 0
    }
}

操作方法

array.concat([a,b,c])组合成新数组,没有参数的时候,只是返回副本。
array.slice(1,3) 按照python那种方式提取数组,不会影响原始数组
array.splice(1,0,[1,2]) 删除、插入、替换数组

位置方法

indexOf(4,4) 可以查找某个东西的位置,带参数从那个位置开始找。
lastIndexOf()

迭代方法

  • every() 每项运行都运行函数,每一项都返回true,则返回true
  • filter() 返回true的组成新数组
  • forEach() 每一项运行给定函数,没有返回值
  • map() 返回每次调用函数的结果
  • some() 任何一项返回true,就返回true
    function(item,index,array){
    return(item>2);
    }

归并方法

reduce() reduceRight()

var values = [1,2,3,4,5]
var sum = values.reduce(function(prev,cur,index,array){
    return prev+cur
})

DATE类型

var now = new Date() 创建日期当前对象,可传入1970.1.1的毫秒数
var someDate = new Date(Date.parse("May 25, 2005")) 按照日期格式转换
var someDate = new Date(Date.UTC(2005,4,5,17,55,55)) 按照0的基数
var start = Date.now() 取得当前时间
valueOf返回毫秒表示,方便比较
toString和toLocalString 返回字符串

RexExp类型

暂缺

Function类型

function sum(num1, num2){
return num1 + num2
}
var sum = function(num1,num2){
return num1 + num2;
};
末尾分号

没有重载

函数声明与函数表达式

率先读取声明,读取到规定地方才读取表达式
function sum(sum1, sum2){} //这是声明,函数声明提升
var sum = function (){} //这是表达式

作为值的函数

把一个函数作为另一个函数的结果返回.return function(){}

函数内部属性

arguments 传入对象的所有参数
this 执行环境,在不同的环境表示
arguments.callee 是函数自己 比如阶乘可以用
caller 保存着调用当前函数的函数引用。

function outer(){
    inner()
}
function inner(){
    inner.caller;  //outer();
}

arguments.callee.caller 更松散的耦合

函数的属性和方法

length 函数希望接收的命名参数的个数
prototype 属性,不可枚举,for-in无法发现
apply() 可以扩充作用域,在特定作用域中调用函数
call() 与apply作用相同,区别是接受参数的方式不同,传递的参数必须枚举出来

function sum(num1,num2){
    return num1+num2
}
function callSum1(num1,num2){
    return sum.apply(this,arguments);
}
function callSum2(num1,num2){
    return sum.apply(this,[num1,num2]);
}
function callSum3(num1,num2){
    return sum.call(this,num1,num2);
}
扩充作用域
window.color = "red"
var o = {color:blue}
function saycolor(){alert(this.color)}
saycolor.call(0)

bind() 绑定作用域

window.color = "red"
var o ={color:"blue"}
function sayColor(){
    alert(this.color)
}
var objectSayColor  = sayColor.bind(o);
objectSayColor(); //blue 

基本包装类型

var s1 = "some text"
var s2 = s1.substring(2);

实际上完成的是以下操作
var s1 = new String("some text");
var s2 = s1.substring(2)
s1 = null

Boolean类型

因为所有对象会转换成true,所以用处不大。
valueOf() 返回基本类型true和false
toString() 返回字符串true
typeof基本类型会返回boolean,引用类型返回object,理解引用关系非常重要。
永远不要使用Boolean 对象

Number类型

var numberObject = new Number(10)
valueOf()返回基本类型的数值
toLocalString和toString返回字符串形式
num.toFix(2) 返回指定小数位,四舍五入
typeof基本类型返回number
typeof引用类型返回object

String类型

valueOf toString toLocalString 返回字符串
使用toString用于将数值格式化为字符串方法

字符方法
stringValue.charAt(1) //访问指定位置
stringValue.charCodeAt(1) //访问指定位置的编码
stringValue[1] //访问指定位置
操作方法
stringValue.concat("world") //字符串连接
slice substr substring //子字符串

indexOf lastIndexOf //位置方法
trim() //删除空格
toLowerCase toUpperCase //大小写转换
match() //接收正则表达式或者RegExp对象
search() //接收正则表达式或者REgExp对象 返回第一个匹配是索引
replace() //替换 可以用正则表达式
localeCompare() //方法

单体内置对象

Golbal对象

URL编码方法
encodeURI() //整个URL编码,不会对本身属于URL字符编码冒号斜杠
encodeURLComponent() //对一段编码,对任何非标准字符编码。
decodeURL()
decodeURLComponent() 解压

eval方法
解析语句

Golbal对象属性
各种类型,构造函数,错误,日期,regexp等

windows对象
访问Global对象,Web浏览器都是将这个全局对象作为windows对象实现。

Math对象

底数,自然数,最大值,最小值,四舍五入,随机数

第六章 面向对象的程序设计

var person = new Object();
person.name = "abc";
person.sayName = function(){
    alert()
}

var person = {
    name:"abc",
    age:29.
    sayName:function(){
        alert(this.name);
    }
}

属性类型

数据属性
[[Configurable]] 能否删除重新定义
[[Enumerable]] 能否通过for-in 循环返回属性
[[writable]]
[[Value]] 这个属性的数值

Object.defineProperty(aaa,"name",{
    writable:false,
    value:"aaaa"
})

访问器属性
[[Configurable]] 能否删除重新定义
[[Enumerable]] 能否通过for-in 循环返回属性
[[get]]读取属性调用的函数
[[set]]写入属性调用的函数

aaa._age=87;

Object.defineProperty(aaa,"age",{
    get:function(){
        return this._age;
    },
    set:function(newValue){
        this._age=newValue;
    }
})

aaa.age=88
alert(aaa.age)

定义多个属性

var book={};
Object.defineproperties(book,{
    _year:{
        value:2004
    },
    edition:{
        value:1;
    }
}
)

读取属性的特性
Object.getOwnPropertyDescriptor(book,"year")
如果是访问属性,那么是configurable,enumerable,get,set
如果是数据属性,那这个对象属性有configurable\enumerable\writable和value
var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
descriptor.value

创建对象

工厂模式

function createObject(name,age,job){
    var person = new Object;
    person.name = name;
    person.age = age;
    person.job = job;
    person.sayName = function(){
        alert(this.name)
    }
    return person;
}

无法解决对象识别问题

构造函数模式

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName = function(){
        alert(this.name);
    }
}
var person1= new Person("johnny",18,"workker")

没有显式创建对象,直接将属性和方法赋给this对象,没有return语句。构造函数要大写。
person1.constructor == Person //true
person1 instanceof Person //true
每次执行方法,都要重建一次。两个创造出来的sayname不相同。把函数移到外面,但是没有封装了。

原型模式

function Person(){}

Person.prototype.name = "Johnny"
Person.prototype.age = 20
Person.prototype.job = "Software Engineer"
Person.prototype.sayName = function(){
    alert (this.name);
}

var person1 = new Person()
person1.sayName();
var person2 = new Person()
person2.sayName();
alert(person1.sayName == person2.sayName); //true 

Person.prototype.isPrototypeOf(person1) //true
Object.getPrototypeOF(person1).name //"Johnny"

无法通过对象实例重写原型中的值,重写之后会给实例添加属性,却不能改写原型。使用delete删除属性,从而回复对原型的访问。使用person1.hasOwnProperty('name') 是否存在于实例中。

原型与in操作符
如果对象能通过原型或者实例访问到属性,in返回true。

确定是原型中的属性。

function hasPrototypeProperty(object,name){
    return !object.hasOwnProperty(name) && (name in object);
}

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

原型简写

function Person(){}
Person.prototype = {
    constrotor : Person,
    name:"abc", 
    sayName : function(){
        alert(this.name);
    }
}
Object.defineProperty(Person.prototype,"constructor",{
    enumerable:false,
    value:Person
}
);

取得对象上可枚举实例的属性

var keys = Object.keys(Person.prototype);
alert(keys);  //"name,age,job,sayName"

取得所有实例的属性,无论是否可枚举

Object.getOwnPropertyNames(Person.prototype);

要不然constructor无法确定对象类型。但是变成可枚举的enumerable。

更简单的原型语法

function Person(){}
Person.prototype = {
    constructor:Person,
    name:"Nicho",
    
    age:18,
    sayName:function(){
        alert(this.name);
    }
};

这样从这里创建的新对象的constructor就不再指向Person了。所以要重写constructor.但是会导致constructor 的Enumerable特性被设置成true。

Object.defineProperty(Person.prototype,"constructor",{
    enumerable:false,
    value:Person
})

原型的动态性
重写一个原型属性可以,但是重写整个原型会导致指向他的实例失去属性。

原型对象问题
没有传递参数,共享本性。

原型对象的问题
所有的实例在默认情况下都使用相同的属性。

组合使用构造函数模式和原型模式。

function Person(name, age, job){
    this.name = name;
    this.age=18
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}

使用最广泛、认同度最高

动态原型模式

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    if (typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name);
        }
    }
}

不能使用对象字面量重写原型,会切断联系。

寄生构造模式

先不看了

稳妥构造模式

先不看了

继承

 function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property
}
function SubType(){
    this.subproperty = false
}

SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function(){
    return this.subproperty;
}

var instance = new SubType();
alert(instance.getSuperValue())

//确定原型和实例的关系
instance instanceof Object
instance instanceof SuperType
instance instanceof SubType
Object.prototype.isPrototypeOf(instance)
SuperType.prototype.isPrototypeOf(instance)
SubType.prototype.isPrototypeOf(instance)

谨慎定义方法,覆盖方法,给原型添加方法一定要放在替换语句之后。
重写subtype会阻断与super之间的联系。
不能通过字面量添加新方法,这样会重写原型。

SubType.prototype  = {
    getSubValue:function(){
        return this.subproperty;
    },
    
    someOtherMethod: function(){
        return false;
    }

}

问题1 ,引用类型的原型,原型会变成另一个类型的实例,实例对原型的修改,提现在了其他的实例上。在创建子类型的时候,不能向超类型的构造函数传递参数。

借用构造函数???

function SuperType(name){
this.color = [1,2,3,"name"]
}
function SubType(){
SubType.call(this,"haha");
}
var instance1 = new SubType();
instance1.push("black")
var instance2 = new SubType();
instance2.color //没有变化

可以传递参数.缺点都在构造函数中定义,无法重复使用,超类型中定义的方法,在子类型中不可见。

组合继承????

function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
alert (this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}

SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("Nicholas",29);
instance1.color.push("black");
alert(instance1,colors); //四个颜色
instance1.sayName(); //nigulasi
instance1.sayAge(); //29

var instance1 = new SubType("aaa",28);
instance1.color.push("black");
alert(instance1,colors); //三个颜色
instance1.sayName(); //aaa
instance1.sayAge(); //28

既避免了原型链和借用构造函数的缺陷,又融合了有点,是最常用的继承模式。

原型式继承

寄生式继承

寄生组合式继承

第七章 函数表达式

函数声明,函数声明提升。
函数表达式,类似于赋值语句。

递归

arguments.callee 返回函数本身,多用于递归。

闭包

你可能感兴趣的:(Javascript高级程序设计笔记)