%……%菜鸟程序员成长记

javascript高级程序设计(第三版)读书书笔记(一)

2017-11-12  本文已影响32人  2857b61e8161

《JavaScript高级程序设计》(第三版)这本红皮书应该是很有名了,买这本有一年了,断断续续的看了前七章,收获很多。趁着周末,刚好把之前记的纸质笔记记录到简书上。

1、如果在函数中使用var定义一个变量,是局部变量,如果省略了var就是全局变量。

function test() {
  var message = "hi"; //局部变量
}
test();
alert(message);//报错

function test2() {
message2 = "hi";//全局变量
}
test2();
alert(message2);//hi

2、五种基本数据类型:Undefined Null Boolean Number String,还有一种复杂数据类型Object。

3、typeof:检测给定变量的数据类型。

typeof null //object

4、Undefined类型:使用var声明变量,但为对其初始化时。

5、Null类型:只有一个值null。空对象指针。如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null,这样只要检查null值就可以知道相应的变量是否已经保存了一个对象的引用。

var car = null;
if(car!=null) {
 对car对象执行某些操作
}

alert(undefined==null);//true

6、Boolean类型:有两个值true和false,这两个值与数字值不是一回事,因此true不一定等于1,而false不一定等于0。对任何数据类型的值调用 Boolean()函数,而且总会返回一个Boolean值。

Boolean(0);//false
Boolean("");//false
Boolean(NaN);//false
Boolean(undefined);//false
Boolean(null);//false

7、NaN:非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数为返回数值的情况。任何数值除以非数值会返回NaN。NaN与任何值都不相等,包括NaN本身。

8、数值转换:有三个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat(),第一个函数可以用于任何数据类型,而另外两个函数则专门用于把字符串转换成数值。

Number(true);//1
Number(false);//0
Number(null);//0
Number(undefined);//0
Number("123");//123
Number("011");//11
Number("");//0
Number("hi");//NaN

parseInt("1234blue");//1234
parseInt("");//NaN
parseInt(22.5);//22

parseFloat("1234blue");//1234
parseFloat("0xA");//0
parseFloat("22.5");//22.5
parseFloat("22.5.5");//22.5

9、String类型:

String(null);//"null"
String(undefined);//"undefined"

10、Object类型:创建Object实例的方式有两种,第一种是使用new操作符后跟object构造函数,第二种是对象字面量表示,Object的每个实例都具有下列属性和方法:

var o = new Object();
var person = {
  name:"kele",
  age:18
}

constructor:保存着用于创建当前对象的函数,上面例子,constructor就是Object()。

hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是实例的原型中)是否存在。o.hasOwnProperty("name")

isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型。

propertyIsEnumberable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。

toLocalString():返回对象的字符串表示。
toString():返回对象的字符串表示。
valueOf():返回对象的字符串、数值或布尔值表示。

11、逻辑与:逻辑与操作可以用于任何类型的操作数,而不仅仅是布尔值。在有一个值不是布尔值的情况下,逻辑与操作就不一定返回布尔值,此时遵循下列规则:

var a = true;
var result = a && b;/会报错,因为b未声明
alert(result);//这一行不会执行

var b = false;
var c = b && d;
alert(c);//false

12、逻辑或:

var a = true;
var result = a || b;
alert(result);//true

var b = false;
var c = b || d;//报错
alert(c);//不执行

13、break和continue语句:break语句立即退出循环强制继续执行循环后面的语句,而continue会退出循环之后会从循环的顶部继续执行。

var num = 0;
for(var i=1;i<10;i++){
  if(i%5==0) {
      break;
}
  num++
}
alert(num);//4
var num =0;
for(var i=1;i<10;i++){
  if(i%5==0){
    continue;
}
num++;
}
alert(num);//8

14、函数:用function关键字来声明,函数会在执行完return语句之后停止并立即退出,return之后的任何代码永远不会执行。函数体内可以通过arguments对象访问参数数组,从而获取传递给函数的每一个参数。可以向函数传递任意数量的参数。

function howManyArgs() {
  alert(arguments.length);
}
howManyArgs("string",45);//2
howManyArgs();//0

arguments对象中的值会自动反映到对应的命名参数上。

function test(num1,num2) {
  arguments[1]=10;
  alert(arguments[0]+num2);
}

每次执行test()函数都会重写第二个参数,将第二个参数修改为10,因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[1],也就修改了num2。这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。如果只传入了一个参数,那么为arguments[1]设置的值不会反映到命名参数中,因为arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
未指定返回值的函数返回的是一个特殊的undefined。

15、函数没有重载,定义了两个名字相同的函数,则该名字只属于后定义的函数。

function test(num) {
  return num+100;
}
function test(num) {
  return num+200;
}
var result = test(100); //300

16、变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,引用类型指的是由多个值构成的对象。

17、复制变量值:引用类型和基本类型值除了保存的方式不同之外,在从一个变量向另一个变量复制时,也存在不同。如果从一个变量向另一个变量复制基本数据类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

var num1 = 5;
var num2 = num1;

在num1中保存的是5,当使用num1初始化num2时,num2中也保存了5。但num2中的5与num1中的5是完全独立的。

当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象的值复制一份放到新变量分配的空间中。不同的是,这个值的副本是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。

var obj1 = new Object();
var obj2 = obj1;
obj1.name = "kele";
alert(obj2.name);//kele

18、传递参数:ECMAScript中所有函数的参数都是按值传递的。把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

function test(num){
  num += 10;
  return num;
}
var count = 20;
var result = test(count);
alert(count);//20 没有变化
alert(result);//30


function setName(obj) {
    obj.name = "kele";
}
var person = new Object();
setName(person);
alert(person.name);//"kele"

function setName2(obj) {
  obj.name = "hi";
  obj = new Object();//引用的局部对象
  obj.name = "hello";
}

var person2 = new Object();
setName2(person2);
alert(person2.name);//"hi"

19、instanceof:检测引用类型的值。在检测一个引用类型值和Object构造函数时,instanceof操作数始终会返回true。如果检测基本数据类型的值,则返回false。

alert(a instanceof Object);
alert(a instanceof Array);

20、垃圾收集:javascript具有自动垃圾收集机制,javascript中最常用的垃圾收集方式是标记清除。另一种叫做引用计数。

21、执行环境有全局执行环境和函数执行环境,全局环境只能访问在全局环境中的变量和函数,局部环境不仅有权访问函数作用域中的变量,还可以访问包含父环境乃至全局环境。

22、使用不带圆括号的函数名是访问函数指针,而非调用函数。

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

var anotherSum = sum;
alert(anotherSum(10,10));//20

sum=null;
alert(anotherSum(10,10));//20

23、函数声明与函数表达式的区别:解析器会率先读取函数声明,并使其在执行任何代码之前可以调用,函数表达式则必须等到解析器执行到它所在的代码行,才会真正被执行。

alert(sum(10,10));//20 正常执行
function sum(num1,num2) {
 return num1+num2;
}

alert(test(20,20));//会报错
var test = function(num1,num2) {
 return num1+num2;
}

24、作为值的函数:不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。例如,假设有一个对象数组,我们想要根据某个对象属性对数组进行排序。而传递给数组sort()方法的比较函数要接收两个参数,即要比较的值。可是,我们需要一种方式来指明按照哪个属性来排序。要解决这个问题,可以定义一个函数,它接收一个属性名,然后根据这个属性名来创建一个比较函数。

function createCompareFunction(propertyName){
  return function(object1,object2){
    var value1 = object1[propertyName];
    var value2 = object2[propertyName];

    if(value1 < value2) {
        return -1;
    }else if(value1>value2){
        return 1;
    }else{
        return 0;
    }

  }
}

var data = [{name:"Zachary",age:28},{name:"Nicholas",age:29}];
data.sort(createCompareFunction("name"));
alert(data[0].name);//Nicholas

data.sort(createCompareFunction("age"));
alert(data[0].name);//Zachary

25、函数内部属性:函数内部有两个特殊的对象:arguments和this。其中,arguments是一个类数组对象,包含着传入函数中的所有参数。这个对象还有一个callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

function test(num) {
  if(num<=1){
  return 1;
}else{
  return num*arguments.callee(num-1);
 }
}
var test2 = test;
test = function() {
  return 0;
}
alert(test2(5));//120
alert(test(5));//0
window.color = "red";
var o = {color:"blue"};

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

函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境变量中执行,全局的sayColor()函数

25、ECMAScript5规范了函数对象的属性:caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局函数中调用当前函数,它的值为null。

function outer(){
  inner();
}

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

以上代码会导致警告框中显示outer()函数的源代码。因为outer()调用了inner(),所以inner.caller就指向了outer()。也可以通过arguments.callee.caller来访问相同的信息。

function outer() {
  inner();
}
function inner() {
  alert(arguments.callee.caller);
}
outer();

当函数在严格模式下运行,访问 arguments.calleearguments.caller会导致错误。严格模式下不能为caller属性赋值,否则会导致错误。

26、ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:lengthprototypelength属性表示函数希望接收的命名参数的个数。

function sayName(name){
  alert(name);
}

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

function sayHi(){
alert("hi");
}
alert(sayName.length);//1
alert(sum.length);//2
alert(sayHi.length);//0

27、对ECMAScript中的引用类型,prototype是保存它们所有实例方法的真正存在,toString()方法和valueOf()等方法都保存在prototype中,通过各自对象的实例访问。ECMAScript5中,prototype属性是不可枚举的。

28、每个函数都包含两个非继承而来的方法:apply()call()。两个方法的用途都是在特殊作用域中调用函数,实际上等于设置函数体内this对象的值。首先apply()方法接收两个参数:一是在其中运行函数的作用域,另一个是函数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。

function sum(num1,num2){
  return num1+num2;
 }
function callSum1(num1,num2){
  return sum.apply(this,arguments);//传入arguments对象
}
function callSum2(num1,num2){
  return sum.apply(this,[num1,num2]);//传入数组
}
alert(callSum1(10,10));//20
alert(callSum2(10,10));//20

29、call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对象call()方法,第一个参数是this没有变化,变化的是其余参数都直接传递给函数。在使用call()方法时,传递给函数的参数必须逐个列举出来。

function sum(num1,num2){
  return num1+num2;
}
function callSum(num1,num2){
  return sum.call(this,num1,num2);
}
alert(callSum(10,10));//20

传递参数并非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);//blue

30、ECMAScript5还定义了一个方法:bind()。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

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

function sayColor(){
  alert(this.color);
}

var objectSayColor = sayColor.bind(o);
objectSayColor();//blue

这些是看这本书的前六章的笔记,后面还会记录之后几章的笔记。买的尤克里里回来了,买的苹果电脑也到了,双十一什么也没买,但是依然要吃吐了,捂脸。。。

要多看书,多写笔记,多敲代码,要不然都对不起这么贵的MacBook Pro....

上一篇 下一篇

猜你喜欢

热点阅读