Javascript知识点总结

本文为阅读《javascript语言精粹》的总结,部分摘自《javascript语言精粹》该书。

 

1.js的简单数据类型包括数字、字符串、布尔值、null值和undefined值。其他所有的值都是对象。数字、字符串和布尔值“貌似”对象,因为它们拥有方法,但它们是不可变的。JavaScript 中的对象是可变的键控集合(keyed collections)。 在JavaScript中,数组是对象,  函数是对象,正则表达式是对象,  当然,对象自然也是对象。对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除undefined值之外的任何值。                                          

2.js包含一种原型链的特性,允许对象继承另一个对象的属性。正确的使用它能够减少对象初始化时消耗的时间和内存。 

3.对象字面量——即包围在一对花括号中的零或多个“名/值”对。对象字面量可以出现在任何允许表达式出现的地方。类似于python中的字典的键/值对。

对象实际上是“名/值”对的集合并拥有一个连到原型对象的隐藏连接。对象字面量产生的对象连接到object.prototype。函数对象连接到function.prototype(该原型对象本身连接到object.prototype)。每个函数在创建时会附加两个隐藏属性:函数的上下文和实现函数行为的代码。(js在创建一个函数对象时,会给该对象设置一个“调用”属性。当js调用一个函数时,可以理解为调用此函数的“调用”属性)。

每个函数在创建时也随配一个prototype属性。它的值是一个拥有constructor(构造函数)属性且值即为该函数的对象。这和隐藏连接到function.prototype完全不同。

4.原型(prototype)

    每个对象都连接到一个原型对象,并且它可以从中继承属性。通过对象字面量创建的对象都连接到object.prototype,它是js中的标配对象。原型连接只有在检索值的时候才被用到。如果我们尝试去获取对象的某个属性值,但该对象没有此属性名,那么JavaScript 会试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从它的原型中寻找,依此类推,直到该过程最后到达终点0bject.prototype。  如果想要的属性完全不存在于原型链中,那么结果就是undefined值。这个过程称为委托。

   原型关系是一种动态的关系。如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。

  原型链:每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
于是就这样一直找下去,也就是我们平时所说的原型链的概念。

5.typeof——确定属性的类型。

原型链中任何属性都会产生值。

另一个方法是使用hasOwnProperty方法,如果对象拥有独有的属性,它将返回true,hasOwnProperty方法不会检查原型链。

6.delete运算符会删除对象的属性。如果对象包含该属性,那么该属性就会被移除,它不会触及原型链中的任何对象。删除对象的属性可能会让来自原型链中的属性透现出来。

eg:var test1 = object.create(test);

     test.name = "hh";

     test1.name = "lala";

     delete test1.name;

     console.log(test1.name)  // ="hh"

7.减少全局变量污染

   法一:为你的应用只创建一个唯一的全局变量;

   法二:使用闭包进行信息隐藏。

8.因为函数是对象,所以它们可以像其他的任何值一样被使用。函数可以保存在对象、变量和数组中(怎样保存在数组中?求知道的大神解答)。函数可以被当作参数传递给其他函数,函数也可以再返回函数。而且因为函数是对象,所以函数可以拥有方法。函数的与众不同之处在于它们可以被调用。

9.函数与方法:

    函数(function)是可以执行的js代码块,由js程序定义或js实现预定义。函数可以带有实际参数或者形式参数,用于指定这个函数执行计算要使用的一个或多个值,而且还可以返回值,以表示计算的结果。

    方法(method)是通过对象调用的js函数,也就是说,方法也是函数,只是比较特殊的函数。

    主要不同之处:

     (1).方法中的数据是隐式传递的;

     (2).方法可以操作类内部的数据;

    方法和对象相关,函数和对象无关;java中只有方法,C中只有函数,而C++里取决于是否在类中。

10.函数字面量

    函数对象通过函数字面量来创建。

   函数字面量包括4个部分。第一部分是保留字function;第二部分是函数名,可以被省略。函数可以用它的名字递归的调用自己,此名字也能被调试器和开发工具用来识别函数。如果没有给函数命名,则被称为匿名函数(anonymous);第三部分是包围在圆括号中的一组参数。多个参数用逗号分隔。这个参数的名称将被定义为函数中的变量。它们不像普通的变量那样被初始化为undefined,而是在该函数被调用时初始化为实际提供的参数的值;第四部分是包围在花括号中的一组语句。这些语句是函数的主体,它们在函数被调用时执行。

   函数字面量可以出现在任何允许表达式出现的地方。函数也可以被定义在其他函数中。一个内部函数除了可以访问自己的函数和变量,同时它也能自由访问把它嵌套在其中的父函数的参数和变量。通过函数字面量创建的函数对象包含一个连到外部上下文的连接。这被称为闭包(closure)。它是js强大表现力的来源。

11.调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数还接受两个附加的参数:this和arguments(实参)。参数this在面向对象编程中非常重要,它的值取决于调用的模式。js中一共有4种调用模式:方法调用模式、函数调用模式、构造器调用模式以及apply调用模式。这些模式在如何初始化关键参数this上存在差异。

    调用运算符即为跟在任何产生一个函数值的表达式之后的一对圆括号。圆括号内包含表达式,每个表达式产生一个参数值。每个参数值被赋予函数声明时定义的形式参数名。当实参(arguments)的个数与形参(parameters)的个数不匹配时,不会导致运行时错误。如果实参过多,超出的参数值会被忽略,如果实参过少,缺失的值被替换为undefined。对参数值不会进行类型检查:任何类型的值都可以被传递给任何参数。

12.方法调用模式

当一个函数被保存为对象的一个属性时,我们称其为方法,当一个方法被调用时,this被绑定到该对象。如果调用表达式包含一个提取属性的动作(.点表达式或->subscript下标表达式),那么它就被当作一个方法来调用。

 方法可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改。this到对象的绑定发生在调用的时候。这个“超级”延迟绑定(very late binding)使得函数可以对this高度复用。通过this可以取得它们所属对象的上下文(context)的方法称为公共方法(public method)。(//这句没看懂,,超级延迟绑定为什么可以使得函数对this高度复用?)

13.上下文(context)

函数使用它们实参的值 来计算返回值,成为该函数调用表达式的值。除了实参之外,每次调用还会拥有另外一个值——本次调用的上下文——这就是this关键字的传值。

如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法。当通过这个对象来调用函数时,该对象就是此次调用上下文(context),也就是该函数的this的值 。用于初始化一个新创建的对象的函数称为构造函数。

上下文->挂载着变量与函数的对象。

14.函数调用模式

    当一个函数并非一个对象的属性时,那么它就是被当作一个函数来调用的;

    以此模式调用函数时,this被绑定到全局对象。(Javascript语言精粹p28、29页)。这是语言设计上的一个错误。倘若语言设计正确,那么当内部函数被调用时,this 应该仍然绑定到外部函数的this变量。这个设计错误的后果就是方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定了错误的值,所以不能共享该方法对对象的访问权。幸运的是,有一个很容易的解决方案:如果该方法定义一个变量并给它赋值为this,那么内部函数就可以通过那个变量访问到this。按照约定,我把那个变量命名为that 。

15.构造器调用模式

    js是一门基于原型继承的语言。这意味着对象可以直接从其他对象继承属性。该语言是无类型的。如果在一个函数的前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype(原型)成员的新对象。同时this会绑定到那个新对象上。

   eg:var test = new test()   //其中test为一个构造器函数

    一个函数如果创建的目的就是希望结合new前缀来调用,那么它就被称为构造器函数。

17.Apply调用模式

    因为js是一门函数式的面向对象编程语言,所以函数可以拥有方法。apply方法让我们构造一个参数数组传递给调用函数。它也允许我们选择this的值,apply方法接收两个参数,第一个是要绑定给this的值,第二个就是一个参数数组。

18.参数

当函数被调用时,会得到一个“免费”配送的参数,那就是arguments数组。函数可以通过此参数访问所有它被调用时传递给它的参数列表,包括那些没有被分配给函数声明时定义的形参的多余参数。这使得编写一个无须指定参数个数的函数成为可能。由于语言的一个设计错误,argumengts并不是一个真正的数组。它只是一个“类似数组(array-like)”的对象。arguments拥有一个length属性,但它没有任何数组的方法。

19.返回

一个函数总是会返回一个值,如果没有指定返回值,则返回undefined。如果函数在调用时在前面加上了new前缀,且返回值不是一个对象,则返回this(该新对象)。

20.扩充类型的功能

    js允许给语言的基本类型扩充功能。eg:通过给object.prototype添加方法,可以让该方法对所有对象都可用。这样的方式对函数、数组、字符串、数字、正则表达式和布尔值同样适用。通过给基本类型增加方法,可以极大提高语言表现力。因为js原型继承的动态本质,新的方法立刻被赋予到所有的对象实例上,哪怕对象实例是在方法被增加之前就已经创建好了。

21.递归

递归函数就是会直接或间接的调用自身的一种函数。递归是一种强大的编程技术,它把一个问题分解为一组相似的子问题,每一个都用一个寻常解去解决。一般来说,一个递归函数调用自身去解决它的子问题。

经典例子:汉诺塔游戏

   其中一个寻常解如下:

 

其中disc表示圆盘,数字1-3表示圆盘的编号,1最小,3最大,src表示源柱子,dst表示目标柱子,aux表示辅助柱子 。

递归函数可以非常高效的操作树形结构,比如浏览器端的文档对象模型(DOM)。每次递归调用时处理指定的树的一小段。

22.作用域

    作用域控制着变量与参数的可见性及生命周期。它减少了名称冲突并且提供了自动内存管理。

    javascript有函数作用域。意味着在函数中的参数和变量在函数外部是不可见的,而在一个函数内部任何位置定义的变量,在函数内部的任何地方都可见。js缺少块级作用域,最好的做法是在函数体的顶部声明函数中可能用到的所有变量。

23.闭包

    作用域的好处是内部函数可以访问定义它们的外部函数的参数和变量(除了this和arguments)。内部函数拥有比外部函数更长的生命周期。

函数可以访问它被创建时所处的上下文环境,这被称为闭包。(javascript语言精粹p38)(闭包有什么好处呢)

24.模块

    我们可以使用函数和闭包来构造模块。模块是一个提供接口却隐藏状态与实现的函数。通过使用函数产生模块,我们几乎可以完全摒弃全局变量的使用。模块模式利用了函数作用域和闭包来创建被绑定对象与私有成员的关联。

    模块模式的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数;最后返回这个特权函数,或者把它们保存到一个可以访问到的地方。(没看懂模块,,有什么作用呢?)

25.级联

    一些方法没有返回值。eg:一些设置或修改对象的某个状态却不返回任何值的方法。如果我们让这些方法返回this而不是undefined,就可以启用级联。在一个级联中,我们可以在单独一条语句中依次调用同一个对象的很多方法。

26.柯里化

    柯里化(curry)允许我们把函数与传递给它的参数相结合,产生出一个新的函数。

27.记忆(memoization)

    函数可以将先前操作的结果记录在某个对象里,从而避免无谓的重复运算。这种优化被称为记忆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值