zoukankan      html  css  js  c++  java
  • javascript语言精粹——笔记

    看书过程中,简单的记录一下重点,回顾起来更方便。

    第二章

    数字

    javascript只有一个数字类型,在内部被标识为64位的浮点数

    标识符

    标识符必须以字母,下划线或者美元符号开头,其他字符可以是字母,下划线,美元符号或者数字

    字符串

    javascript的String类型是由零个或者多个16位Unicode字符组成的字符序列,即字符串。

    字符串不可变。通过+连接得到的是一个新的字符串。

    js的原始类型的值都是不可变的,操作得到的是一个新的值(其他地方看到的)

    语句

    for...in语句可以枚举一个对象的所有属性

    Object.hasOwnProperty()当属性存在于对象实例中时,返回true。in操作符只要能够找到属性,就会返回true。

    typeof运算符,如果运算数是数组或者null,那么结果是Object。

    +可以做加法操作,也可以链接字符串。如果想要进行数字加法,确保操作数都是数字

     如果第一个运算数是假,运算符&&产生的第一个运算数的值。否则,产生第二个运算数的值

     如果第一个运算数是真,运算符||产生的第一个运算数的值。否则,产生第二个运算数的值

    表达式

    js中%不是通常数学意义上的模板运算,而实际上是求余运算。两个运算数都是正数时,求模运算和求余运算值是相同的。两个运算数中存在负数时,求模运算和求余运算的值则不相同。(具体查询请看这里)(求余运算和求模运算,对于不同的语言,不同的系统,可能会有不同的标准,有些规定余数要大于0,有些规定余数绝对值尽量小,由此可能得出不同的运算结果)

    第三章: 对象

    js中除了简单类型数字,字符串,布尔值,null和undefined之外,都是对象。

    数组也是对象,函数也是对象,正则表达式也是对象。

     对象是属性的容器,属性包含名字和值。名字可以是包含空字符串在内的任何字符串。值可以是除undefined之外的任何值。

     字面量

    如果是合法的标识符作为对象的属性名称,可以省略引号。(可以养成写标识符的良好习惯)

    检索

    如果检索一个不存在的属性,返回undefined

    如果检索一个undefined属性的值,TypeError

     引用

    对象通过引用来传递。它们永远不会被复制。

    原型

    每个对象都连接到一个原型对象,并从中继承属性。

     创建一个新的对象时,可以选择一个对象作为原型。下面是实现object.create

    if(typeof Object.create !== function){
      Object.create = function(o){
        var F = function(){}
        F.prototype = o
        return new F()
      }
    }
    

     原型连接在更新时不起作用。对对象作出改变,不会影响到对象的原型。

    原型链接只有在检索值得时候才被用到。如果在对象中没有找到,会试着从原型对象中获取属性值,直到终点Object.prototype。这个过程称为委托。

     原型关系是动态的关系,如果添加属性到原型中,立即对基于该原型创建的对象可见。

    反射

    hasOwnPrototype方法只检查对象中所有的属性,不会检查到原型链上。

     枚举

    for in遍历一个对象时,遍历对象中所有的属性名。包含函数以及原型中的属性。可以使用typeof function和hasOwnproperty方法来过滤。

    删除

    删除操作也不会触及原型链中的任何对象

     减少全局变量污染

    为你的应用创建一个唯一的全局变量。另一种方法是闭包

    第四章:函数

    函数对象

    js函数就是对象。函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)。

    每个函数在创建时会附加两个隐藏属性:函数的上下文和实现函数行为的代码(js在创建一个函数时,会给该对象设置一个“调用”属性)。

    函数是对象,可以像其他任何的值一样被使用。可以保存在变量、对象和数组中。可以当做参数传递给其他函数,函数也可以返回函数。函数也可以拥有方法。

     函数字面量

    函数参数将被定义为函数中的变量。在函数被调用时初始化为实际提供的参数的值

    内部函数可以访问自己的变量和参数,也可以自由访问嵌套在其中的父函数的参数和变量。通过函数字面量创建的函数对象包含一个连到外部上下文的连接,被称为闭包(closure)

     调用

    调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数还接收两个附加的参数:this和arguments。(this和arguments在函数调用时才绑定)

    this的值取决于调用的模式。

    js中有四种调用模式:方法调用模式,函数调用模式,构造器调用模式和apply调用模式。

    方法调用模式

    函数被保存在对象的一个属性时,称它为一个方法。

    方法被调用时,this绑定到该对象。

    this绑定发生在调用时。

    通过this可取得所属对象的上下文的方法称为公共方法(??用来干什么呢)

    函数调用模式

    当一个函数并非一个对象的属性时,被当作一个函数来调用。

    this绑定到全局对象(严格模式下undefined)。这是一个语言设计上的错误,正确设计的情况下,内部函数被调用时,this应该绑定到外部函数的this变量。解决方案:该方法定义一个变量并给它赋值为this,内部函数可以通过访问那个变量访问到this。一般使用that变量名。

     构造器调用模式

    如果一个函数前面带上new来调用,背地里将会创建一个连接到该函数的prototype成员的新对象,this绑定到该新对象上。

    Aplly调用模式

    使用函数的方法apply,选择传递一个this给该函数

    参数

    函数被调用时,会得到一个免费配送的参数,arguments数组(类数组,有length属性)。

     返回

    函数执行完毕,会把控制权交还给调用该函数的程序。

    遇到有大括号或者return语句,函数执行完毕

    递归

    经典“汉诺塔”问题。

    深度递归可能会因为堆栈溢出而运行失败。(ES6增加了尾递归优化,可以解决溢出问题)

     作用域

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

    js有函数作用域。(ES6的块级作用域,let和const关键字必须)

     闭包

    函数可以访问它被创建时所处的上下文环境。这称为闭包。

    内部函数能够访问外部函数的实际变量而无须复制。经常遇到的for循环问题,for循环中生命变量var i=0,相当于在外部上下文中声明了一个变量,如果在for循环中创建函数,访问的i是外部环境的i。例子看下面

    var add_the_handlers = function(nodes){
      var i
      for(i=0;i<nodes.length;i++){
        nodes[i].onclick = function(e){
          alert(i)
        }
      }
    }
    

    避免在for循环中创建函数,它可能会带来无谓的计算,还会引起混淆。

     模块

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

    级联

    如果让没有返回值得函数返回this而不是undefined,可以启用级联。

    柯里化

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

    function curry(fn) {
      var args = Array.prototype.slice.call(arguments, 1)
      return function () {
        var innerArgs = Array.prototype.slice.call(arguments)
        var finalArgs = args.concat(innerArgs)
        return fn.apply(null,finalArgs)
      }
    }
    

     记忆

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

    var memoizer = function (memo, formula) {
      var recur = function(n){
        var result = memo[n]
        if(typeof result !== 'number'){
          result = formula(recur,n)
          memo[n] = result
        }
        return result
      }
      return recur
    }
    

     斐波那契数列

    var fabonacci = memoizer([0,1],function (recur,n) {
      return recur(n-1) + recur(n-2)
      })
    

    阶乘

    var factorial = memoizer([1,1],function(recur,n){
      return n*recur(n-1)
    })
    

     继承

    伪类

    通过构造函数产生对象。当一个函数被创建时,Function构造器产生的函数对象会运行类似这样的一些代码:this.prototype={constructor:this};新函数对象被赋予一个prototype属性,它的值是一个包含constructor属性且属性值为该函数的对象。

    js所有函数都会得到一个prototype对象。

     第六章:数组

    javascript的数组本质上是一种类数组的对象。

    它把数组下标转变为字符串,用其作为属性。数组的第一个值将获得属性名‘0’,第二个值得属性名为‘1’。

    同对象一样,数组可以包含不同类型的元素。

     不同:数组继承自Array.prototype,对象继承自Object.ptototype。所以数组有大量有用的方法。

     长度

    javascript的数组的length是没有上限的。

    通过改变length,可以删除元素(设置一个新的小的length)

    length不一定等于数组中元素的个数。(var a[10]=1,只有一个属性但是length为10)

     枚举

    因为数组是对象,for in可以枚举数组的所有属性,但是for in不能保障元素的顺序。

    for循环可以按照顺序来访问元素属性。使用下标。

     容易混淆的地方

    在javascript编程中,使用数组或者对象,选择可是根据以下规则:如果属性名时小而连续的整数时,应该使用数组。否则,使用对象。

    判断一个对象是否为数组:

      Object.prototype.toString.apply(value) === '[Object Array]'

    方法

    数组其实就是对象,可以直接给数组添加方法。

    毒瘤

    1. 全局变量(直接声明的var变量;window添加属性;未声明使用的变量)
    2. 作用域(最好的方式,在开头声明所有变量)
    3. 自动插入分号(规范编码风格,或者使用lint工具帮助规范代码风格)
    4. 保留字(最好的方式,不要使用)
    5. unicode,ES6之前unicode的单个字符被识别为两个字符(使用es6编码,然后babel转换)
    6. typeof,针对null,数组,正则表达式等返回的值并不如意(记住特殊情况)
    7. parstInt遇到非数字就停止(建议:使用时一定要加上基数)
    8. +(如果需要进行数字加法,一定要保证操作数都是数字)
    9. 浮点数,小数运算结果不准确(整数运算正确,小数运算指定精度)
    10. NaN(Number.isNaN()检测)
    11. 伪数组:性能比真正的数组差很多(只能提高引擎了吧)
    12. 假值(空字符串、0,false,null,undefined,NaN)
    13. hasOwnPproperty(作为一个方法,可以容易的被覆盖,一定要注意)
    14. 对象(js的对象并没有真正的空对象,总是从Object继承一些东西。)

    糟粕

    1.  ==(请始终使用===和!==)
    2. with(万不得已,不要使用)
    3. eval (没有把握,不要使用)
    4. continue影响代码性能(寻找替代方法)
    5. switch case穿越(没太明白,如果你的代码出现问题,可以特别注意一下)
    6. 缺少{}(尽量不要省略{},压缩后的代码只多了几个字符而已)
    7. ++/--,不谨慎的编码可能造成安全漏洞(还没有意识到会造成什么漏洞)
    8. 位运算:js位运算性能很差,尽量不要使用(其他语言可能更贴近硬件,使用效率比较高)
    9. function声明和function表达式(作者一直使用函数表达式,提升可能会造成一些问题?嗯……)
    10. 类型的包装对象(不要使用new Boolean,new Number,new String)
    11. new运算符经常会被遗忘()

     JSON

    使用JSON.parse,而不要使用eval。parse可以在发现危险数据时发出警告,错误。

    PS:直接把服务器传来的html给innerHTML是一个危险的行动,如果html中有恶意脚本的话。

  • 相关阅读:
    MySQL++:MySQL 复合索引、普通索引总结
    AutoCAD 二次开发之python(学习中)
    APScheduler 学习笔记
    pylint 定制化配置/使用 -待整理
    JDK和CGLIB动态代理区别
    Java 类加载过程
    判断字符串是否是数字类型
    Java 并发编程锁工具
    花式写挂
    WC2021 题目清单
  • 原文地址:https://www.cnblogs.com/Jamie1032797633/p/11844810.html
Copyright © 2011-2022 走看看