JavaScript 进阶营让前端飞程序猿阵线联盟-汇总各类技术干货

JavaScript高级程序设计 3rd Edition 读书笔

2018-03-09  本文已影响37人  GunnerAha

第一章 JavaScript简介

  1. JavaScript组成:

第二章 在HTML中使用JavaScript

  1. 使用<script>标签引用JavaScript脚本:
  1. 不设置defer/async属性的前提下,JavaScript文件顺序加载。
  2. <script>的位置:
  1. 在XHTML中,特殊字符需要使用转义符号\转义或者使用<![CDATA[code]]>引用JavaScript代码块。

第三章 基本概念

  1. 语法特性:
  1. 使用var定义的变量为局部变量,不使用var修饰的变量是全局变量。
  2. 松散数据类型,可以使用typeof操作符检测变量数据类型:
  1. Ojbect类型共有的属性和方法:
  1. 操作符:与Java类似,有符号右移>>,无符号右移>>>。相等操作符:==,比较时会自动进行转换,例如:'55'==55结果是true;全相等操作符:===,值和类型必须都相等,例如:'5555'===555结果是false。此外,null==undefined结果为true,null===undefined结果为false。
  2. for-in语句:
for(property in expression)
{
    statements;
}
  1. with语句:将代码的作用域设定在一个特定的对象中,不推荐使用
  2. 函数:
function functionName(arg0...)
{
    statements;
}

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

  1. 5中基本数据类型是按值访问的。引用数据类型是保存在内存中的值,不能直接操作对象的内存空间,实际上操作的是对象的引用。因此,引用类型的值是按引用访问的。
  2. 引用类型的值,可以为其动态添加/改变/删除属性和方法。
  3. 函数参数是按值传递的,基本类型会创建局部变量,引用类型传递的是对象的引用,操作时会改变对象本身。
  4. 判断变量引用类型使用instanceof。
  5. 延长作用域的语句:
  1. 全局执行环境是windows对象,每个函数拥有自己的执行环境。函数中的变量访问不能跨越自己的执行环境。
  2. 没有块级作用域:
if(true)
{
    var color='blue';
}
alert(color);//提示blue

特别注意for循环中的迭代i,执行完毕后alert(i)是可以输出最终值的。

  1. 使用var声明的变量自动加入到函数内部的局部环境中,没有使用var声明,自动添加到全局环境中。
  2. JavaScript的垃圾处理方法:标记清除/引用计数。
  3. 引用数据类型不使用后,设置为null可以释放其应用。

第五章 引用类型

  1. Object类型的创建:
  1. Object对象属性的访问可以使用.和[]进行访问,如person.name或者person['name']。
  2. Array类型表示数组,创建方式:
  1. Array常用函数:
  1. Date类型:创建new Date()
  2. RegExp类型:正则表达式对象,语法:var expression=/pattern/flags,其中flags取值g全局/i不区分大小写,m多行模式。创建:
  1. Function类型:函数也是对象,函数调用:sum()
var sum=function(num1,num2){return num1+num2;}

等价于:

function sum(num1,num2){return num1+num2;}
  1. 函数内部属性:
  1. 函数的属性和方法:
  1. 基本包装类型:Boolean/Number和String。引用类型与基本包装类型的主要区别是对象的生存期,使用new创建的引用类型的实例,一直保存在内存中,而基本包装类型的对象,只存在代码执行的瞬间,因此不能在运行时添加属性和方法,因为对象已经销毁。
var s1="some text";
var s2=s1.substring(2);

s1是基本类型字符串,但是却可以使用方法,原因是后台解析是自动执行了:

var s1=new String("some text");
var s2=s1.substring(2);
s1=null;//正是这句改变了包装类型的生存期
  1. Object/Array/String/Date/RegExp等都是内置对象(ECMAScript默认提供,不依赖宿主环境的对象),单体内置对象有Global和Math:

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

  1. JavaScript使用Object创建对象并为其添加属性/方法。
  2. ECMAScript的两种属性:
var person={};
Object.defineProperty(person,'name',{writable:false,value:'Nicholas'});
var book={_year;2004,Edition;1};//_开头的属性约定表示只能通过访问器访问
Object.defineProperty(book,'year',
{
    get:function(){return this._year;},set:function(newValue){this._year=newValue;}
}
);
  1. 通过函数Object.defineProperties(待添加或修改的对象,{多个属性内容})定义多个属性。
  2. 通过Object.getOwnPropertyDescriptor(对象,属性)获取指定属性的描述符。
  3. 创建对象new和字面量较繁琐,可以使用如下方法创建对象:
function createPerson(name,age)
{
    var o=new Object();
    o.name=name;
    o.age=age;
    o.setName=function(){alert(name);};
    return o;
}
function Person(name,age)
{
    this.name=name;
    this.age=age;
    this.sayName=function(){alert(name);};
}

构造函数的特点是,不同实例会有多个方法function。因此,通常的做法是定义函数,然后在构造函数中传入函数的引用。

function Person()={}
Person.prototype.name='Gunner'';
Person.prototype.age=1;
Person.prototype.sayName=function(){alert(this.name)};
var person1=new Person();
person1.sayName();

或者可以省略多次重写prototype:

function Person(0{}
Person.prototype={
    name:'Gunner',age:1,sayName;function(){alert(this.name)}
}

原型模式的缺点是数据的共享。对于基本类型数据没有问题,但是对于引用数据类型,会造成不同对象修改某一个后另一个对象的引用数据类型类型的值也做了修改。

funciton Person(name,age)
{
    this.name=name;
    this.age=age;
    this.friends=['gunner','gonner'];
}
Person.prototype={
    constructor:Person,//会自动添加
    sayName:function(){alert(this.name);}
};
function Person(name,age)
{
    this.name=name;
    this.age=age;
    if(typeof this.sayName !='function'){
    Person.prototype.sayName=function(){alert(this.name)};
    }
}
function Person(name,age)
{
    var o=new Object();
    o.name=name;
    o.age=age;
    o.sayName=function(){alert(this.name);};
    return o;
}
function Person(name,age)
{
    var o=newObject(0;
    o.setName=function(){alert(name);};
    return o;
}

该模式下除了使用sayName()方法外,没有其它方法能够访问name值。

  1. 继承:ECMAScript没有函数签名,因此没有接口继承,只支持实现继承。实现继承的方式
function SuperType(){
    this.property=true;
}
SuperType.prototype.getSuperValue=function(){
    return this.property;       
}

function SubType(){
    this.subproperty=false;
}
//继承SuperType
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
    return this.subproperty;
}
var instance=new SubType();
alert(instance.getSuperValue());//true

给原型添加方法的代码一定要放到替换原型的语句之后。并且通过原型链实现继承时,不能使用对象字面量创建原型方法。即不能使用:

SubType.prototype=new SuperType();
SubType.prototype={
    getSbuValue:function(){
        return this.subproperty;
    }
};

原型链的问题与使用原型创建对象的问题类似,即引用对象的共享问题。

function SuperType(){
    this.colors=['red','blue'];
}
function SubType(){
    //继承SuperType
    SuperType.call(this);
}

借用构造函数的问题是函数不能重用

function SuperType(name){
    this.name=name;
    this.colors=['red','blue'];
}
SuperType.prototype.sayName=function(){
    alert(this.name);
}

function SubType(name,age){
    //继承属性
    SuperType.call(this,name);
    this.age=age;
}
SubType.prototpype=new SuperType();
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function(){
    alert(this.age);
}
function object(o){
    function F(){}//临时构造函数
    F.prototype=o;//将传入的对象作为这个构造函数的原型,实际是对象的浅复制
    return new F();
}

ECMAScript5规范化了原型继承模式Object.create(用作新对象原型的对象,[新对象定义额外属性的对象])。第二个参数为空等同于调用object()。

var antherPerson=Object.create(person,{
    name:{value:'Gunner'}
});
function createAnother(original){
    var clone=object(original);//通过调用函数创建新对象
    clone.sayHi=function(){//以某种方式来增强对象
        alert('Hi');    
    };
    return clone;
}
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); //创建对象
    prototype.constructor = subType; //增强对象
    subType.prototype = prototype; //指定对象
}

这个函数接收两个参数:子类型构造函数和超类型构造函数。在函数内部,第一步是创建超类型原型的一个副本。第二步是为创建的副本添加 constructor 属性,从而弥补因重写原型而失去的默认的 constructor 属性。最后一步,将新创建的对象(即副本)赋值给子类型的原型。完整代码如下:

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;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
};
上一篇 下一篇

猜你喜欢

热点阅读