读<>

作者: BeADre_wang | 来源:发表于2017-12-15 15:32 被阅读0次

    第二章:在HTML中使用JS

    2.1  <script>标签重要属性

            async:表示立即下载脚本,但不该妨碍页面中其他的操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效。

            defer:表示脚本可以延迟到文档完全被解析和显示后再执行。只对外部脚本文件有效。

            src:

            type:表示要编写代码使用的脚本语言的内容类型(MIME类型)

    除此之外,使用<script>标签嵌入JS代码的时候,代码中不要出现字符串“</script>”,会被默认认为其是结束的标签,必须要转义,如:"<\/script>"才行。

    2.2 使用外部脚本的优点

          1.可维护性:开发人员可以在不触及HTML标记的情况下,集中编辑JS代码。

          2.可缓存:如果有两个页面都使用的同一个JS文件,那么这个文件只需要被下载一次。

    2.3 <noscript>元素

         该标签是可以指定在不支持脚本的浏览器中所显示的替代内容,启用脚本之后,浏览器不会显示该标签中任何内容:如  <noscript>  <p>本页面需要浏览器支持(启用)JS</p></noscript>

    第三章:基本概念

    number:   var num1 = parseInt("10",2);  //2(按二进制解析)     

                         var num2 = parseInt("10",8); //8(按八进制解析)

    string:    1.  null和undefined没有toString的方法,需要用String方法

                        2. toString方法前面是变量,如10.toString(2)会报错,需要先把10赋值给一个变        量,如var num=10,num.toString(2)才行。

    Object:

    1.Object的每个实例都有下面属性和方法

       constructor:保存着用于创建当前对象的函数。

       hasOwnProperty(propertyName):用于检查给定属性在当前当前实例中(而不是在实例原型中)是否存在,其中,作为参数的属性名必须用字符串形式指定(object.hasOwnProperty("name")).

       isPrototypeOf(object):用于检查传入的对象是否是另一个对象的原型。

       propertyIsEnumerable(propertyName):用于检查给定属性是否能用for-in语句来枚举,同样的属性名必须用字符串形式制定。

      toString():返回对象的字符串表示。

    valueOf():通常和toString()的返回值相同

    第四章:变量、作用域和内存

    4.1:基本类型和引用类型的值

    ⑴基本类型的值不能添加属性(尽管不会导致任何错误),引用类型的值可以添加属性方法

    ⑵从一个变量向另外一个变量上复制基本类型的值,会在新变量对象上创建一个和该值相同的新值,两个值互相操作不影响;而引用类型则是复制一个指针,和前一个变量一样指向的是储存在堆内存中的同个对象。因此,改变其中一个变量,就会影响另一个变量。如下图:

    第五章:引用类型

    5.1:Object类型

        (1)两种方式访问对象属性:person.name和person["name"],后者的好处是可以通过变量来访问属性以及当属性名包含导致错误语法的字符。如果不是必须,通常建议用第一种方法访问属性

    5.2:Array类型

       (1)访问数组中不存在或者未赋值的项返回的是undefined,如数组长度是3,你访问array[3]。

       (2)检测是否是数组一般直接用Array.isArray(array)方法,因为instanceof方法在多于一个框架的情况下会有多个不同的原生数组的构造函数

       (3)当数组中的某个值为null或者undefined时使用join、toString、valueOf方法返回的是空字符串

       (4)数组模拟栈方法(后入先出,最后一项被移除)  使用push和pop方法

       (5)数组模拟队列方法(先入先出,第一项被移除)  使用push和shift方法

       (6)slice:两个参数时返回起始到结束的项。包含开始项,不包含结束项。

       (7)splice:①删除:指定两个参数,删除第一个参数项的位置和删除的项数 如splice(0,2)会删除                                    数组中的前两项。

                      ②插入:可以向指定位置插入任意数量的项数  如splice(2,0,"red","blue"),原数组会在第                                 三项后面插入两个颜色字符串。当前返回的是一个空数组。

                      ③替换:可以像指定位置插入任意数量的项,且同时删除任意数量的项  如 splice(2,1,"red","blue")会删除并返回第三项,原数组会在第三项的位置插入两个颜色字符串。

    (8)数组的迭代方法:每个参数接收两个参数,第一个是要给数组每项执行的函数和(可选的)运行该函数的作用域对象。传入的函数会接收三个参数:数组项的值、值的索引、数组本身

      ①every():对数组的每一项都运行该函数,如果该函数对每一项都返回true,则返回true。该函数返回的是布尔值。

      ②filter():对数组的每一项都运行该函数,返回该函数会返回true的项组成的数组。

      ③forEach():对数组的每一项都运行该函数,该方法没有返回值。

      ④map():对数组的每一项都运行该函数,返回每次函数调用的结果组成的数组。

      ⑤some():对数组的每一项都运行该函数,如果该函数对任意一项返回true,则返回true。

    以上的方法都不会修改原数组的值。

    (9)数组的缩小方法:reduce()和reduceRight()。也是接收两个参数,一个是调用的函数和(可选的)作为缩小基础的初始值。调用的函数接收4个参数:前一个值、当前值、值的索引和数组对象。

    5.3:Date类型

    5.4:Function类型

       (1):因为函数也是对象,所以函数名实际是指向函数对象的一个指针,不会与某个函数绑定。

      (2):解析器会率先读取函数声明,并使其在执行任何代码前可用;而函数表达式则必须等到解析器执行到它所在的代码行才会被真正解析执行。

      (3):arguments.callee:指向拥有这个arguments对象的函数(严格模式下访问会出错)

    5.5:String类型

    (1):indexOf():可以用该函数来匹配字符串里所有的给定字符

    (2):trim():创建一个字符串副本,去除字符串前置及后缀所有空格;该方法是为所有字符串创建的方法;例如:str.trim()

    第六章:面向对象的程序设计

    6.1.1:属性类型 (为实现JS引擎用的内部属性) :数据属性和访问器属性

    1.数据属性:

         [[configurable]]:表示能否通过delete删除属性,能否修改属性的特性或者能否把属性修改为访问器属性;默认值为true。(改为false将不能改回true)

        [[enumerable]]:表示能否通过for-in循环返回属性;默认值是true。

        [[writable]]:表示能否修改属性值;默认值是true。

        [[value]]:包含属性的数据值。默认值是 undefined。

    2.访问器属性:

       [[configurable]]:表示能否通过delete删除属性,能否修改属性的特性或者能否把属性修改为访问器属性;默认值为true。

      [[enumerable]]:表示能否通过for-in循环返回属性;默认值是true。

      [[get]]:在读取属性时调用的函数。默认值是 undefined。

      [[set]]:在写入属性时调用的函数。默认值是 undefined。

    以上属性都是通过Object.defineProperty()方法修改:如Object.defineProperty(对象名,属性,{configurable:false})则该对象的该属性不可被删除

    6.2创建对象

    6.2.1创建对象之工厂模式

        该模式的缺点是没有解决对象识别的问题(就是该模式是直接创建对象然后将其返回出去,它相当于是。person1.constructor和instanceof不等于createPerson)

    6.2.2创建对象之构造函数模式

       直接将属性和方法赋给this对象,然后用new关键字来创建实例,这样该实例的constructior会指向构造函数并且可以通过instanceof知道该实例是构造函数的实例。

      缺点:是构造函数里的方法会在每个实例被重新创建一次,比如构造函数上面有一个sayName的方法,那就会在每个实例上都创建一个该方法,但是创建两个及更多完成同样任务的Function是没必要的。

    6.2.3创建对象之原型模式

       1. 方法:将属性和方法直接添加到构造函数的prototype中,然后用new关键字来生成实例。

     2.原型与in操作符:通过in操作符和hasOwnProperty()可以确定属性是在实例上还是在原型上;

     3:for-in、Object.keys()、Object.getOwnPropertyNames()三种可以遍历对象属性的方法。

        for-in是返回当前对象及其原型上所有可枚举的属性;Object.keys()是返回当前对象上所有可以枚举的属性; Object.getOwnPropertyNames()是返回当前对象上所有的属性,不管是否可以枚举

     4:缺点

        ⑴:它省略了为构造函数传递初始化参数这一过程,导致所有实例在默认情况下都将取得相同的属性值。

       ⑵:致命问题是当某个属性是包含引用类型值的时候(如数组),问题就很突出。就是当某个实例修改了含引用类型值的时候(如数组中的值被添加或者删除),那修改的数组会在所有实例中反映出来。

    6.2.4组合使用构造函数模式和原型模式

      1. 方法:构造函数用于定义实例属性,而原型模式用于定义方法和共享属性

      2. 缺点:构造函数和原型分开写看着可能让其他OO经验的人员感到困惑

    6.2.5动态原型模式

      1. 方法:只是将上种方法设计的所有信息封装在构造函数中

    2.缺点 :没缺点,完美。其中的if语句检查的可以是任意一种初始化后应该有的方法或者属性,不必检查每个属性和每个方法,只需检查一个就行。

    6.3继承

         实例永远指向的是构造函数的原型而不是构造函数

    6.3.1原型链继承

      1.原型链:比如一个实例的原型指的是其构造函数的原型(假定为A),而A也是其他构造函数的实例(假定为B),这时A的原型指向为B的原型,那假设B的原型也是其他构造函数的实例,那么上述关系依然成立,如此层层递进就形成了原型链

     2.例子:下例SuperType的原型指向的是Object的实例(实例是对象),Object的实例的原型为null

      3.缺点:6.23的缺点。

    6.3.2借用构造函数继承

       缺点:和6.22缺点相同。除此之外,在SuperType的原型上定义的方法或者属性,SubType的实例访问不到,因为它们的原型指向的是SubType的原型。

    6.3.3组合继承

     1.方法:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例的继承

      2.缺点:无论什么情况下,都会调用两次SuperType函数。一次在创建子类型原型的时候,一次在子类型构造函数内部。

    6.3.4原型式继承

       方法:使用Object.create()方法。第一个参数是用作新对象原型的对象,(可选的)第二个参数是为新对象添加的额外属性的对象,格式为{name:{value:"wanghao"}}。

      原理:只传一个参数的情况例子如下:

    缺点:当传入对象的某个属性值为引用类型(如数组)的话,只要生成的任意一个实例添加,删除,修改该数组的值,都会在所有实例中反映出来。因为所有实例中该数组的属性名字只是指向内存中该引用类型的一个指针。

    6.3.5寄生组合式继承:将6.3.3组合继承中的缺点改正了,将创建子类型原型的那一行代码改成了调用inheritPrototype函数。

    第七章:函数表达式

       函数声明提升:意思是执行代码之前会优先读取函数声明。

    7.3:模拟块级作用域:创建匿名函数自运行;优点是避免全局变量过多、造成污染和减少其占用的内存问题,因为只要该匿名函数执行完毕,就会销毁其作用域链。

    7.4:私有变量:任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。我们把有权访问私有变量和私有函数的公有方法称为特权方法。有两种在对象上创建的特权方法:

        1:构造函数中定义特权方法

       2:原型模式

    第八章:BOM

    8.1:全局作用域:

      (1)使用var声明的全局变量不能通过delete删除,而直接使用window对象上定义的属性可以删除。

      (2)尝试访问未声明的变量会跑出错误,而通过window对象查询该属性,会返回undefined。

    8.2:打开新窗口:window.open()方法。该方法可接收4个参数:url地址、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。通常只需传第一个参数,最后一个参数只在不打开新窗口的情况下使用。

    8.3:超时调用和间歇调用:setInterval和setTimeout;超时调用的代码都是在全局作用域中执行的,所以其this在严格模式中指向undefined,非严格模式指向window。

    8.4:位置操作

    (1):location.assign()方法。为其传递一个url地址就能打开新url并在历史记录中生成一条记录

    (2):location.href="url地址",该方法是调用(1)方法。

    (3):location.replace()方法。为其传递一个url地址就能打开新url并不会生成历史记录。

    (4):location.reload();重新加载当前页面(有可能从缓存中加载)

    (5):location.reload();从 服务器重新加载当前页

    (6):history.back():后退一页。

    (7):history.forward():前进一页。

    第十三章:事件

      13.1:

     (1):addEventListener(),removeEventListener();都接收三个参数:要处理的事件名、作为事件处理的函数和一个布尔值。如果最后这个布尔值为true,表示在捕获阶段调用函数;如果是false,表示在冒泡阶段调用函数。还有就是通过addEventListener()添加的匿名函数是无法移除的。事件名不需要加on:如“click”。

     (2):在IE中对应的是attachEvent(),detachEvent();都接收相同的两个参数:要处理的事件名、作为事件处理的函数;所有事件处理程序都会被添加到冒泡阶段执行。事件名需要加on:如“onclick”。还有就是事件处理程序是按照相反的添加顺序执行的(也就是最先添加的最后执行)

    13.2:移除事件处理程序

          当使用removeChild()、replaceChild()、innerHTML移除或者替换页面的某一部分时。如果带有事件处理程序的元素被替换、删除掉,那么原来添加到元素中的事件处理程序极有可能无法被当作垃圾回收。如下图;所以最好手工移除事件处理程序,如下图注释行。除此之外还可以用事件委托解决该问题,将事件指定给被替换掉部分更高层次的元素上

    第十四章:表单脚本

    14.1:可以用document.forms["表单名"]来访问表单,用form.elements[0或者name特性]来访问表单中的元素。

    14.2:可以用element.focus()方法让某个输入框自动聚焦(也可以直接给元素加autofocus属性,不过为了兼容应该判断if(element.autofocus !== true){element.focus});

    14.3:可以用size特性来指定input框的显示字符,用maxlength来指定其可接受的最大字符。在textarea中可以结合focus事件和select()方法来让文本域获得焦点时自动选中所有文本。

    第十七章:错误处理与调试

    17.1:处理错误:try-catch语句。try{//可能导致错误的代码}catch{//在错误发生时怎么处理}当try块中的任何代码发生错误时,会立即退出代码执行过程,然后执行catch块。此时,catch块会受到一个包含错误信息的对象。不管你是否使用它,也要给它起名字。

    17.2:finally字句:不管try和catch解析哪个,finally子句中的代码块都会执行。

    17.3:throw:抛出自定义的错误。解析器遇到throw操作符时,代码会停止执行。

    第二十章:JSON:是一种轻量级数据格式

    20.1:语法。JSON语法包含以下三种类型值

       1、简单值:使用与JS相同的语法,可以在JSON中表示字符串、数值、布尔值和null,但不支持undefined。

      2、对象:每个键值对的值可以是简单值,可以是复杂数据类型(对象,数组)。

      3、数组:数组中每个值也可以是任意类型,

    JSON不支持变量、函数或者对象实例。JSON中字符串必须使用双引号属性名必须加双引号(单引号会导致语法错误)。

    20.2:解析与序列化

     1、JSON.stringify():用于把JS对象序列化为JSON字符串。该方法接收三个参数:第一个为序列化的js对象;第二个是个过滤器,该参数可以是一个数组,可以是一个函数;第三个参数是一个选项,表示是否在JSON字符串中保留缩进。

      ①当过滤器是数组时:JSON.stringify(obj,["name","age"])返回的是{"name":"wang","age",21}.

      ②当过滤器是函数时:函数接收两个参数:键名和键值。然后在函数里执行相应操作(必须有返回值)

      ③第三个参数可以填数值或者字符串,最大值为10,所有大于10的值或者字符串都会自动转化为10,如果为数值则缩进对应的字符量,如果是字符串则缩进改为字符串。

    2、JSON.parse():用于把JSON字符串解析为原生JS值。该方法接收2个参数,第一个为JSON对象;第二个同样是一个函数,该函数有两个参数,同样需要有返回值。如果返回值是undefined则表示删除相应的键。

    第二十一章:Ajax与Comet

    跨域通信

    1:CORS(跨域资源共享):http://www.ruanyifeng.com/blog/2016/04/cors.html

    2:图像Ping:与服务器进行简单、单向的跨域通信的一种方式。请求的数据是通过字符串形式发送的,而响应可以是任意内容, 但通常是像素图或204(服务器成功处理了请求,但不需要返回任何实体内容)响应。通过图像ping,浏览器得不到任何具体数据,但通过load和error事件,能知道响应是什么时候接收到的。如下列子中发送了一个name参数,无论是什么响应,只要请求完成就能得到通知。缺点是一:只能发送get请求,二是无法访问服务器的文本。因此,图像ping只能用于浏览器与服务器的单向通信。

    3:JSONP:由回调函数和数据组成,回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。相比于图像ping,其优点是能够直接访问响应文本,支持在浏览器与服务器之间的双向通信。不过JSONP的也有两点不足:一是其加载的是其他域的代码,一旦其他域不安全,很可能会夹杂一些恶意代码,而此时除了放弃JSONP调用之外,没有办法追究。二是 jsonp在调用失败的时候不会返回各种HTTP状态码。

    4:WebSocket:目标是在一个单独持久的连接上提供全双工、双向通信。其使用的是自定义协议而不是http协议。自定义协议的优点是能在客户端和服务端发送非常少量的数据,很适合移动端。缺点是制定协议的时间比JS API的时间还要长。

    第二十二章:高级技巧

    22.1:高级函数

    1:作用域安全的构造函数

    如下面例子,第一次undefined是因为Square中的this对象并不是Polygon的实例,所以会创建并返回一个新实例,而Square中的this对象并没有增长得到这个新实例,所以就没有sides属性,其实例也没有sides属性,所以是 undefined。加上光标行的注释之后,就能成功继承sides属性打印出2。

    2:懒性载入函数

    因为浏览器之间行为的差异,所以检查不同浏览器能力的时候会有很多if语句,但是当其支持某个功能能力之后,其这个能力会一直存在,以后调用该函数时就没必要再去一一检查了,如下

    3:函数绑定

    如下面例子,第一次打印undefined是因为this指向的是DOM按钮button,而button并没有message属性;第二次是使用闭包直接调用handleClick方法让this指向handle;第三次是用bind方法让其指向handle。而bind是为函数定义的原生方法,其接收2个参数:第一个为调用该方法的函数的执行环境(作用域)。第二个会作为调用该方法的函数的第一个参数,也就是下例handleClick函数的一个参数。

    22.2:防篡改对象

    1:不可拓展对象:可以使用Object.preventExtensions(obj)方法将obj对象改为不可拓展状态,也就是说不能在向该方法中的参数obj对象添加任何属性和方法;在非严格模式下会添加失败,而在严格模式下继续添加属性或者方法会报错。可以修改或者删除对象中原有的方法或者属性。使用Object.isExtensible(obj)来判断对象是否为可拓展状态

    2:密封的对象:使用Object.seal(obj)来将对象密封,密封以后不能添加任何方法或者属性,也不能删除对象中原有的方法及属性,但是可以修改方法或者属性。同样在严格模式下还是会报错。使用Object.isSealed(obj)来判断对象是否为密封状态。

    3:冻结的对象:使用Object.freeze(obj)来将对象冻结,冻结以后不能添加,修改,删除任何方法或者属性,换句话说,就是该对象本身不可改变。同样在严格模式下还是会报错。使用Object.isFrozen(obj)来判断对象是否为冻结状态。

    第二十三章:离线应用与数据存储

    23.1:cookie的读取,写入和删除。

    23.2:web的存储机制(即Storage:Storage只能存储字符串,其他类型在存储时会被转换成字符串)

         (1)sessionStroage:可以用length属性和key()方法迭代sessionStorage中的值

                      还可以用for-in来迭代sessionStorage中的值

    (2)localStroage与上述相同

    第二十四章:最佳实践

    24.1:可维护性

    1、可读性:下列情况加注释:①函数或方法:描述其目的和可能使用的方法。②大段代码:用于完成单个任务的多行代码应在前面加注释。③复杂的算法:帮助别人或者以后自己的观看。

    2、变量和函数命名:起语义化的名字,返回布尔值的函数用is来开头。

    3、变量类型透明:①初始化:当定义变量后,用初始化的值来暗示其类型(var num=1;//说明num是数值类型)。②匈利亚标记法:在变量第一个字符加上其类型单词的首个字母(var Nnum=1)。③加注释。

    4、松散耦合:①解耦HTML/JS:将html文件和JS文件分开,并避免在JS中创建大量HTML;②解耦CSS/JS:避免直接用JS修改元素的样式,而是去修改元素的样式类(修改其className);③解耦应用逻辑/事件处理程序:一个事件处理程序应该从事件对象中提取相关信息,并将这些信息传到处理应用程序的某个方法中。

    5、编程实践:①尊重对象所有权:即最好不要修改不是由你创建的对象(document,Array等),可以继承你想修改的类型然后在实例中修改。②避免全局量:避免过多的使用全局量,可将这些全局量(变量或函数名)放在一个对象中创建:var myObj={name:"",sayName:function(){}}③类型检测避免与null比较:如果值为引用类型,使用instanceof检查其构造函数;如果值为基本类型,使用typeof检查其类型。

    24.2:性能

    1、注意作用域:①避免全局查找:如全局变量、函数、全局对象(如document)等将在一个函数中引用多次的情况下,将其赋值给一个局部变量来储存。②避免with语句:因为with会创建自己的作用域,因此会增加其中执行代码的作用域链的长度。

    2、选择正确方法:①避免不必要的属性查找:一旦多次用到对象属性,应将其存储在局部变量中。②优化循环:(1)减值迭代:从最大值开始在循环中不断减值的迭代器更高效。(2)简化终止条件:避免属性查找或其他O(n)操作。(3)简化循环体:确保没有某些可以被很容易移出循环的密集计算。(4)使用后测循环,如do-while。③性能的其他注意事项:(1)原生方法较快:原生方法是用诸如C/C++之类的编译性语言编写的,如Math对象中的方法绝对比任何用JS写出来的同样方法快。(2)switch语句较快:如果有一系列if-else语句,可以将其转化为switch语句。(3)位运算符比较快。

    3、最小化语句数①多个变量声明:尽量用一个var来声明多个变量,变量间用逗号隔开。②插入迭代值:如var name = value[i];i++; 可以变为var name = values[i++];③使用数组和对象字面量:即使用[]和{}来创建数组或对象,减少直接用构造函数创建。

    4、优化DOM交互①最小化现场更新:即尽量减少createElement()和appendChild()等DOM方法。②使用innerHTML:该方法比使用多个DOM更快(也尽量少用)。③使用时间代理。④注意HTMLCollection:以下情况会返回HTMLCollection对象:(1)对元素进行getElementByTagName()的调用。(2)获取元素的childNodes属性。(3)获取元素的attributes属性。(4)访问特殊的集合:如document.forms,document.images等。

    5、压缩代码。

    相关文章

      网友评论

          本文标题:读<>

          本文链接:https://www.haomeiwen.com/subject/pnrdwxtx.html