《JavaScript高级程序设计》学习笔记

一个完整的JavaScript实现应由以下三个部分组成:

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

ECMAScript中有五种简单数据类型:

  • Underfined
  • Null
  • Boolean
  • Number
  • String

一种复杂数据类型:

  • Object

注意!

console.log(typeof(null)); //object

with语句会降低性能。

ECMAScript函数命名的参数只提供便利,但不是必须的,不介意传递进去多少个参数,也不在乎传进来参数是什么数据类型。
未指定返回值的函数返回的是一个特殊的undefined值。
ECMAScript中所有的参数传递的都是值,不可能通过引用传递参数。
ECMAScript函数没有签名,因为其参数是由包含零或多个值的数据来表示。因为没有签名,所以没有重载。

JavaScript解释器在执行环境中加载数据时,会率先读取函数声明,使其在执行任何代码之前可用;至于函数表达式,则必须等到解释器执行到它所在的代码行,才会被真正解释执行。

alert(sum(10,10));  
function sum(num1, num2){
   return num1 + num2;     
}

如果将函数声明改为等价的函数表达式,就会在执行期间导致错误。

alert(sum(10,10));  
var sum = function(num1, num2){
   return num1 + num2;     
}

sort函数嵌套:

function createComparisonFunction(propertyName) {
   return function(object1, object2){
       var value1 = object1[propertyName];
       var value2 = object2propertyName];
       
       if(value1 < value2) {
           return -1;
           } else if (value1 > value2) {
            return 1;
            } else {
               return 0;
            }
       };
}

var data = {{name:"test", age:28},{name:"hello", age:"25"}};

data.sort(createComparsionFunction("name"));
data.sort(createComparsionFunction("age"));

函数内部有两个特殊的对象: arguments和this,arguments有一个callee的属性,是一个指针指向拥有arguments对象的函数。

//实现递归
function factorial(num) {
   if(num<=1){
       return 1;
       } else {
           return num*arguments.callee(num - 1);
       }
}

this引用的是函数据以执行的环境对象。当在网页的全局作用域中调用函数时,this引用的是windows.

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

o.sayColor = sayColor;
o.sayColor(); //"blue"

ECMAScript中的函数是对象,每个函数都有两个属性:length和prototype.
length表示函数希望接受的命名参数的个数。
prototype是保存它们所有实例方法的真正所在,诸如toString()和valueFO()等方法都保存在prototype下。
每个函数都包含两个非继承来的方法:apply()和call(),两个方法都在特定的作用于中调用函数,实际上等于设置函数体内this对象的值。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]);
}
alert(callSum1(10,10));   //20
alert(callSum2(10,10));   //20

call()方法与apply()作用相同,区别在于接收参数的方式不同。对于call()方法而言,第一个参数是this值,变化的是其与参数都直接传递给函数。

传递参数并非apply()和call()真正用武之地:它们真正强大的是能扩大函数的作用域。

window.color = "red";
var o = {color:"blue"};

function sayColor(){
   alert(this.color);
}
sayColor();    //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //red

bind()方法创建一个函数的实例,其this值会被绑定到传递给bind()函数的值。

window.color = "red";
var o = {color:"blue"};

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

引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。来看下面的例子:

var s1 = "some text";
s1.color = ""red;
alert(s1.color);     //undefined

ECMA-262 对内置对象的定义是: “由 ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在 ECMAScript 程序执行之前就已经存在了。”意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。

Global(全局)对象可以说是 ECMAScript 中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。ECMAScript 中的 Global 对象在某种意义上是作为一个终极的“兜底儿对象来定义的。换句话说,不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量或全局函数;所有在全局作用域中定义的属性和函数,都是 Global 对象的属性。

当解析器发现代码中调用 eval()方法时,它会将传入的参数当作实际的 ECMAScript 语句来解析,然后把执行结果插入到原位置。通过 eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过 eval()执行的代码可以引用在包含环境中定义的变量,举个例子:

//在环境外定义
var msg = "hello world!";
eval('alert(msg)');   //"hello world!"
//在eval环境内定义
eval("function sayHi() { alert('Hi');}");
sayHi();

window ECMAScript 虽然没有指出如何直接访问 Global 对象,但 Web 浏览器都是将这个全局对象作为window 对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了 window对象的属性。

操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象。在所有代码执行之前,作用域中就已经存在两个内置对象: Global 和 Math 。在大多数ECMAScript实现中都不能直接访问 Global 对象;不过,Web 浏览器实现了承担该角色的 window 对象。

面向对象程序设计

ECMAScript 中有两种属性:

  • 数据属性
  • 访问器属性。
  1. 数据属性
    要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty() 方法。这个方法接收三个参数:
  • 属性所在的对象
  • 属性的名字
  • 一个描述符对象
    其中,描述符(descriptor)对象的属性必须是: configurable 、 enumerable 、 writable 和 value 。设置其中的一或多个值,可以修改对应的特性值。
  1. 访问器属性
    访问器属性不包含数据值;它们包含一对儿 getter 和 setter 函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter 函数并传入新值,这个函数负责决定如何处理数据。

访问器属性不能直接定义,必须使用Object.defineProperty()来定义:

vav book = {
    _year: 2004,
    edition: 1
}

Object.defineProperty(book, "year", {
    get: function(){
        return this._year;
    },
    set: function(newValue){
        if (newValue>2004) {
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
});

book.year = 2005;
alert(book.edition);  //2
function(){
  
}

你可能感兴趣的:(《JavaScript高级程序设计》学习笔记)