Javascript高级程序设计笔记

2017-02-07  本文已影响0人  江上风平浪静

第一章 Javascript简介

Javascript实现

ECMA-262

文档对象模型

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

浏览器对象模型

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

第二章 在HTML中使用JavaScript

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

<script type="text/javascript" src="abc.js"></script>

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

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

外部文件的优点:

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

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

第三章 基本概念

语法

关键字和保留字

不一一列举了。

变量

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

数据类型

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

typeof操作符

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()数值转换规则

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()
每个实例都有下列属性和方法

操作符

一元操作符

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

一元加减操作符。如果是非数值,用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() 相同

逻辑与&&

逻辑或||

乘性操作符

乘法*

除法/

求模%

加性操作符

加法

减法

关系操作符

相等操作符

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

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

条件操作符

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()

迭代方法

归并方法

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 返回函数本身,多用于递归。

闭包

上一篇下一篇

猜你喜欢

热点阅读