精通JavaScript(重点内容笔记)更新中...

 

  本书作者是jQuery之父John Resig的经典之作,是深入学习JavaScript技术的绝佳教材,涵盖了可重用代码、文档对象模型、Ajax、Web生产工具、AngularJs登内容。作者讲解了JS的发展现状、使用技巧以及未来趋势,辅以诸多代码提示,条理清楚、分析到位。本书展示了更新颖、更巧妙、更具有深度的JavaScript技术,同时理清了JavaScript的发展脉络,既能磨练技能,又可开拓视野。

 

第2章 特性、函数和对象

  对象是JavaScript的基本单元。本章包含了JavaScript语言中最为重要的一些方面,例如引用、作用域、闭包以及上下文。它们未必是建造这门语言的基石,却是支撑、改良JavaScript的优美拱梁。

2.1 语言特性

2.1.1 引用和值

  JavaScript采用两种方式来保存数据:值和引用。所有的原始值都直接复制到变量中。原始值包括字符串、数字、布尔值、null 和undefined。原始值最重要的特点是:它们按照值进行赋值、复制、传递函数参数以及返回函数结果。

  JavaScript的其余部分则依赖于引用。没有保存原始值的变量中保存的对象是对象的引用。引用是指对象(数组、日期或是其他)所在位置的指针。实际的对象被称为指称目标(referent)。这是一种存在于多种编程语言中的强大特性。他提高了操作效率:两个(或多个)变量不需要各自拥有某个对象的副本,他们只需要指向同一个对象即可。

  对象拥有两种特性:属性和方法。这两者通常杯统称为对象的成员。属性包含对象的数据。属性可以是原始值,也可以是对象。方法是作用在数据上的函数。在一些关于JavaScript的讨论中,方法被涵盖在属性之中。但有必要对两者做出区分。

2.1.2 作用域

  绝大多数编程语言都采用了某些形式的作用域,差别在于作用域的持续期(duration)。JavaScript中只有两种作用域:函数作用域和全局作用域。函数拥有自己的作用域,而块(如while、if和for语句)则没有。

例2-1 JavaScript中变量作用域的工作方式:

// 将全局变量foo的内容设置为test
var foo = 'test'

// 在if块中
if (true) {
  // 将foo设置为new test
  // 注意:此时处于全局作用域!
  var foo = 'new test'
}

//在这里我们看到foo此时等于new test
console.log( foo === 'new test' );

//创建一个修改变量foo的函数
function test() {
  var foo = 'old test'
}

// 但是在调用函数的时候,变量foo仅存在于函数作用域中
test();

// foo仍然等于new test
console.log(foo)

 

  你会发现变量位于全局作用域中。在基于浏览器的JavaScript中,所有的全局变量实际上是作为window对象的属性存在的。在其他环境中,所有的全局变量属于某个全局上下文。在例2-1中,赋值给了处于test()函数作用域中的变量foo。但是在例2-1中,该变量并没有声明它的作用域(使用var foo),当变量foo没有明确声明作用域时,他会被定义成全局作用域,即使他只是打算在函数中使用。

例2-2 隐式全局变量声明:

// 定义函数,设置变量foo的值
function test() {
    foo = 'test';
}
// 调用函数为foo赋值
test();
// foo现在变成了全局作用域
console.log( window.foo === 'test' );

  函数中 不加var 声明的变量 是全局变量。

  在函数声明变量的时候,要留心变量提升(hoisting)的问题。函数中所有的声明(不包括变量的初始值)都会提升到作用域的顶部。JavaScript以此保证变量名全局可用。

2.1.3 上下文 

  你可以使用变量this来访问上下文,该变量总是指向代码当前所处的执行环境。 

 例2-3 在上下文中使用函数,然后将上下文切换到另一个变量:

function setFoo(fooInput) {
  this.foo = fooInput
}
var foo = 5;
console.log( 'foo at the window level is set to:' + foo );

var obj = {
  foo: 10
}

console.log( 'foo inside of obj is set to:' + obj.foo );

// 修改window对象中的foo
setFoo(15);
console.log( 'foo at the window level is now set to:' + foo );

// 修改对象obj中的foo
obj.setFoo = setFoo;
obj.setFoo(20)
console.log( 'foo inside of obj is now set to:' + obj.foo );
// foo at the window level is set to: 5
// foo inside of obj is set to: 10
// foo at the window level is now set to: 15
// foo inside of obj is now set to: 20

  setFoo函数看起来有点奇怪。我们通常并不会在普通的工具函数中使用this。将setFoo()与obj绑定在一起,利用this来访问obj的上下文。JavaScript有两种方法可以在制定的上下文中运行函数,call()和apply()方法。

例2-4 更改函数上下文:

   // 一个简单的函数,可以用来设置其上下文的文字颜色
  function changeColor(color) {
    this.style.color = color;
  }

  // 在window对象上调用函数时,该函数无法正常运行,原因在于window对象并不包含style对象
  // changeColor('while');

  // 创建一个新的div元素,该元素包含style对象
  var main = document.createElement('div');

  // call方法将div设置为黑色
  // call方法使用第一个参数来指定上下文,并将其余的参数传递给函数
  changeColor.call(main, 'black');

  // 使用console.log检查结果
  // 应该输出“blak”
  console.log(main.style.color);

  // 定义一个函数,用于设置body元素的文字颜色
  function setBodyColor() {
    // apply方法使用第一个参数将上下文设置为body元素,第二个参数是一个传递给函数的参数数组
    changeColor.apply(document.body, arguments);
  }

  // 将body元素的文字颜色设置成红色
  setBodyColor('red')

2.1.4 闭包

  闭包是这样一种手段:通过它,内部函数在其副函数结束之后依然能够引用其外围函数(outer enclosing function)中的变量。

  闭包允许你引用存在于父函数中的变量。但是它提供给你的并不是该变量在创建之时的值,而是其在父函数中最后的那个值。

例2-4:

 

 

 

 

 

 

 

 

posted @ 2019-02-14 11:54  七七。  阅读(362)  评论(0编辑  收藏  举报