继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

《Head First JavaScript》 读书笔记

zhang012
关注TA
已关注
手记 2
粉丝 8
获赞 500

书名:《Head First JavaScript》
中文译名:《深入浅出JavaScript》
著:Michael Morrison
编译:O’Reilly Taiwan公司
出版发行:东南大学出版社
图片描述


申明:
本文所做的笔记并非本书最精华的部分,笔记大多是第一次阅读本书时候所记录下来的本人比较有感触的部分(茅塞顿开?),虽然再次看这些知识点的时候自己也找不到当时初看时候的感觉,但是分享给大家,希望对大家的前端学习有所帮助。


第一章 交互式网络,感觉虚拟世界

本章首先讲述了JavaScript对于网页的重要性,即为网页带来了生命;然后以一个iRock的例子说明了JavaScript是如何为网页带来了生命,使网络呈现出交互性,总得来说属于吸引人继续往下读的章节,本章,我没有做太多有用的笔记。


第二章 存储数据 每项事物都有自己的位置

1、本章主要讲述的是如何呈现数据、存储数据以及找出数据:
2、JavaScript使用三种基本数据类型text、number以及boolean。设定JavaScript的值的时候,即已自动暗示类型。具有极大的灵活性;
3、alert框里列出的数字,其必定为文本类型;
4、设定常量使用const NAME=Value;
5、重新载入网页,脚本回来尚未执行前的状态;
6、标识符:变量,常量及其它JavsScript语法元素在脚本里用作分辨的独一无二的名称,标识符应该具有描述性;
7、创建常量时务必初始化,否则容易引起误解(未初始化undefined表示没有数据);
8、NaN:not a number;非数字,用于表达变量的特殊状况,某个表示应该是数字的值不见了的时候就会出现NaN;
9、常用命名规则:主要采用驼峰型(CamelCase)(首字母也大写)只会用于对象,小写驼峰型则用于变量和函数,常量全部大写;
10、parseInt()与parseFloat():将文本转换为数字(传入的必须为数值,否则NaN);
11、toFixed()函数可以把Number四舍五入为指定小数位数的数字;
12、isNaN()函数,返回两个值,不是数字(true);是数字(false)
13、对象的定义:其是一种先进的JavaScript数据类型,它能结合函数,常量和变量为一个逻辑实体(logical entity),方法(method)其实是属于某对象的函数,特性(property)则是对象里的常量和变量,JavaScript几乎使用对象表达一切;


第三章 探索客户端 浏览器探索

1、浏览器里面允许JavaScript代码的部分叫做JavaScript解释器;
2、JavaScript被称作客户端语言的原因在于,网页不用等待服务器处理和返回数据;
3、关于cookie:

cookie就像变量,浏览器把它存放在用户的硬盘中;
cookie的作用在于延长脚本的生命周期;cookie具有自己的有效日期,甚至都算不上中期的保存方案;
服务器也可以用来永久存储数据,不过小数据的时候不需要小题大做;
readCookie();writeCookie();
cookie影响浏览器的安全性,其本身非安全的存储场所,最好别把敏感数据存储在cookie里;
cookie不能访问用户的硬盘或散步病毒,但是可以存储输入网页的个人数据。
只有在指定的网页里,cookie名称才需要独特,因为cookie存储时会依据创建它们的网页加上区隔,确认cookie在单一网站或网页里面具体独特性;
不同浏览器不能共享cookie的数据的;
cookie只适合存储相对较少的文本数据(小于4kb)cookie效率比较低;
navigator.cookieEnabled用于检查浏览器是否支持cookie;

4、Ajax:编写的向网站请求信息的脚本,然后于网页上呈现信息;
5、单次定时器——setTimeout(Timer code,Timer delay);
6、不管数字多大,都别在JavaScript的数值中加逗号;
7、清除定时器clearInterval(timerID);
8、document.body.clientWidth和document.body.clientHeigth特性里面存储了客户端窗口的宽度和高度;
9、document对象代表网页本身;
10、style.height和style.width,几乎可以改变任何元素的尺寸;
11、要取用网页元素,需要在onload里运行;
12、onresize()事件,检测并响应浏览器窗口尺寸的调整;


第四章 决策 前有岔路,面对抉择

1、分号保留给单一语句使用,复合语句不需要;复合语句里面出现的单一语句还是需要加上分号,但是复合语句本身则不需要;
2、运算符:operator;表达式:expression;
3、只要不是null、0、空字符串(“”),或“未定义”,任何值都会被解读为true;
4、作用域代表数据的上下文;
5、脚本层次:脚本的最上层;
6、创建在函数内的变量为局部变量,其它全部都是全局变量;
7、switch/case语句让我们在许多事物之间有效率的选择,switch后面的表达式,不可为运算式,只能是单纯的数据。


第五章 循环 自我重复的风险

1、数组用于在单一场所存储多段数据;
2、数组的页码称为键(key),索引只是一种形式特殊的键,它是数值键;
3、存储在数组里的数据不一定为相同类型;
4、并不要求二维数组具有相同的行数,但是最好保持一致。


第六章 函数 简化、重复利用、回收再利用

1、解决“大”问题的诀窍,就在于将其分解成较小,较易管理的问题,如果分解后问题还是太庞大,再进一步分解;
2、程序代码分解为函数的原因,在于协助区分工作,并为每个函数赋予单一目的;
3、复制代码是个做成函数的好征兆,另外一个征兆是某段代码逐渐变得笨重庞大,且可以被分解为数个逻辑片段;
4、argument:函数自变量;
5、字面量(literal)是用于表达源代码中一个固定值的表示法;
6、return语句亦可不与任何数据同用,单纯用于提早结束函数;
7、关于函数的进一步理解:

函数只不过是变量,函数不像一般变量,变量将其数据存储成存储器的某个区域里的值,函数则存储对代码的引用。所以函数变量的值不是代码本身,而是指向存储代码的存储器位置的引用;
当函数主体单独出现而没有名称时,又被称为函数字面量(function literal)
函数名称也被称为函数引用(function reference)
引用函数和调用函数的区别在于函数名称后面是否有(),函数引用只会单独出现,但是函数调用则必定后随括号,很多时候还附有自变量;
函数引用让我们联接JavaScript代码设计的事件处理函数,而不需改动HTML代码;
回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数,其重要性在于让我们对代码外发生的事情有所反应,回调函数就是一直在等待某事发生好准备起身动作的函数;
函数字面量有时候被称为匿名函数(anonymous
function),只是没有名称的函数主体,有点像是实际的数据,其重要性在于它们很适合需要快速偶发回调函数的情况,只被调用一次;

8、onload事件处理器是一个初始化所有事件的绝佳地方;
9、onload处理器保证网页一定已经载入,script标签中,网页不一定加载;


第7章 表单与验证 让用户全盘托出

1、id属性可独一无二地识别网页元素,name属性可独一无二地识别表单中的域,以上2、两个属性均可当成input域的识别符;
3、form对象厉害的地方,在于它也是一个数组,负责存储表单中所有域。但是它的数组元素并非利用数值索引存储,而是使用域独有,于name属性设定的标识符;
4、oncharge事件和onblur类似,但它只在某个域不再被选择而且输入内容被改变时触发;
5、有很多响应键盘行为的事件。比如onkeypress,onkeyup,onkeydown;
6、使用<span></span>来添加验证,而不使用烦人的alert();
7、在html元素的上下文中,关键字this指向代表该元素的对象,form属性可以把整份表单当做对象访问,this.form用于引用表单本身。this.form是对form对象的引用;
8、辅助信息的id,命名规则一般为输入域的id后面加上_help;
9、isNaN()函数可检查值是否“不为数字”;
10、数据全部都正确才执行(&&);
11、问题很严重时,值得使用alert框;
12、关于正则表达式:

作用:正则表达式(regular expression)专门设计用于匹配文本模式;
正则表达式使用说明:出现在一对斜线里//;
元符号:用来连接字母和数字,创建高度描述性文本模式的特殊符号;
”.”(点):匹配任何字符,换行符除外(newline);
\s:匹配空格,包括空白字符(space),tab,换行符,renturn/enter;
\d:匹配任何数字字符;
^:字符串需以模式起始,前不能有其它字符;
\w:匹配任何字母数字;
$:字符串需要以此模式结束;
正则表达式:不是元字符的任何文字将于正则表达式里“照样匹配”;
正则表达式限定符(quantifier),限定符前为子模式,限定符即应用在子模式,并且控制子模式出现在模式里地次数:
*:子模式为可选的,可出现任意次数;
{n}:限定符之前的子模式必须恰好出现n次;
+:子模式必须出现,必须出现1次或多次;
?:子模式为可选的,若出现最多只能出现1次(0或1次);
():集合字符或/和元字符,成为子模式;
模式限定:比起只有元字符更加精确,不再直接重复子模式;
正则表达式本身不是字符串,但可以当做是对外部字符串的描述;
正则表达式单纯设计用于匹配文本字符串内的字符模式,所以只能用在字符串上
具有特殊意义的字符,能以\来进行转义匹配。比如匹配$为\$;

13、简单字母串搜索indexOf()其实是极度简化到最简化的模式匹配,此时的模式只是一个静态的词汇或者词语;
14、模式是一组对文本的叙述,但模式不见得必为文本本身;
15、JavaScript的RegExp对象的test()方法用于检查字符串是否包含正则表达式模式;
16、正则表达式中的选替(alternation),类似于JavaScript的OR逻辑运算符,为|单竖线;
17、字符类:在模式里创建受到紧密控制的子模式[],在字符类内,每个列出的字符都是合格的字符匹配目标,能建立可替换的子模式列表;
18、邮件验证的正则表达式:/^[\w.-_+]+@[\w-]+(.\w{2,4})+$/;


第8章 驾驭网页 利用DOM分割HTML

1、关于innerHTML:

innerHTML特性对所有存储在元素里的内容提供了访问管道;
innerHTML特性实际上用于设置内容类元素,例如div、span、p以及其它装载内容的元素;
innerHTML特性一定完全改写任何原有内容,其没有附加的概念;

2、nodeValue特性总是包含纯文本,没有额外格式:存储于节点的值,只限文本和属性节点使用;
3、利用nodeValue特性,可以轻易地指派新文本内容给子节点,但是只在非元素只拥有一个节点,如果拥有多个,只改变第一个;
4、安全的修改内容的方法:移除子节点;根据新内容创建新的文本节点;把新创建的文本子节点附加在节点下:对应removeChild();createTextNode();appendChild();
5、存储在元素中的内容,在DOM树中一定是该元素的子节点;
6、nodeType特性返回的是每种节点类型的代号,TEXT是3,ELEMENT是1;
7、DOM是种符合万维网标准的HTML操纵方式,它能比innerHTML(微软退出,后被其它浏览器采用,但并不是标准)特性达成更多操控功能;
8、createTextNode()创建的文本节点内容只能是文本,不能有其它标签或者附加格式的文本;
9、通过改变样式类的名称可以更改样式;
10、在HTML代码中我们能透过关键字this访问相对于某个元素的对象;
11、节点的style特性提供对单一样式特性的访问;
12、网页元素可以利用元素对象的visibiliey样式特征做动态的显示或隐藏,也可以用display属性。


第9章 为数据带来生命 科学对象怪人

1、对象=数据+行为;
2、对象是个容器,其中存储数据并链接数据与依据数据行动的代码;
3、当变量与函数被放在对象里面时,它们被当成对象成员(object member),变量称为对象的特性(property),函数被称为对象的方法(method);
4、通常运用点号运算符来访问对象的方法和特性.;以点号引用对象成员;
5、对象是一组有名称的特性和方法的集合。其包含多块数据,其可称为complex数据类型;而number,text,boolean被称为基本数据类型;
6、与对象紧密联系的数据,比起在脚本中飘零的一般数据(全局变量),具有更多背景和意义;
7、JavaScript本身就是一个大型的对象集合,比如alert()函数是window对象的方法;
标准JavaScript对象:日期,字符串,数组;
8、构造函数负责创建对象,使用new运算符,它调用对象的构造函数,开启对象创建和过程;
9、构造函数的大部分工作,就是创建对象的特性,还有对象的初始值。在构造函数里创建特性时,需要使用JavaScript的关键字this,其指派对象特性的所有权,同时设置特性的初始值,创建属于“这个”(this)对象的特性,而不是构造函数里的局部变量。this.who=who;
10、构造函数都采用首字母大写,如同对象名称
11、关键字this是于构造函数里创建对象特征的重点;
12、new运算符和构造函数共同创建了对象;
13、构造函数负责创建对象的特性,所以没有构造函数就没有任何特性,没有任何特性就不是一个有意义的对象;
14、this是JavaScript的关键字,用于引用对象;
15、在Date对象里,时间以毫秒数表达;
16、String对象看起来不太像对象,它们只是简单地括起一段文本字符串,创建为对象字面量(object literal);
17、Date对象在于表达瞬间,以1970年1月1日为参考点,以毫秒为单位;
18、对象转换为文本,每个JavaScript对象都具有toString()方法,它试图为对象提供文本字符的表达方式,会主动冒出来工作;
19、getMonth()日期中的月份数,以0到11表示;getDate():一个月中的天数,1到31;getFullYear():完整地四位数年份;
20、Array对象的sort()方法,默认采取由小到大的升幂顺序;
21、字符串里面的字符串被称为子字符串(substring);
22、indexOf()方法:返回子字符串位置的索引值,或者在找不到匹配字符串时返回-1;
字符串可以看成是字符组成的数组;
23、可以把字符串内的字符类比如数组的元素,但是字符串一定不是数组;
24、chartAt()只能搜索单一字符;
25、Math对象是个收藏数学方法和常量的组织对象,其没有变量,不能用于存储任何事物;
26、Math对象并未实际包含可以使用的数据(instance data),所以不需要创建对象,其只是静态的方法和常量的集合;
27、Math.round():四舍五入;Math.floor():直接舍去小数点后面的数字;
28、把一些常用函数加到对象里面去;

 


第10章 创建自定义对象 让你为所欲为

1、方法过载
2对象类:是对象的描述,一份描述对象构成的模板;对象实例:则是实际对象,从类中创建;
3、类描述对象的特性和方法,实例则把真正的数据放入特性,并为数据注入生命,每个实体都有自己的特性副本,实例之间才彼此不同;
4、关键字this用于设置实例拥有的特性和方法,但是this同时表明它们被各个实例所拥有,这就解释了方法会被复制到每个特例(方法过载)的原因;
5、类拥有的实例方法(class-owned instance method),比起每个实例各存储一份方法,有效率多了;
6、方法存储在类里,让所有实例共享一份方法代码;
7、prototype对象用于设定隶属于类层(class level)的特性与方法,而非属于实例的;
8、类是对象的描述,实例则是实际的对象,根据对象描述所创建的;
9、类勾画了对象的特性和方法,实例则把真正的数据放在特性里以供方法利用;
10、关键字this用于从实例本身的程序代码内访问实例;
11、prototype对象让方法可存储于类内,以免实例不必要地一直复制程序代码;
12、类让对象的创建和重复利用更为容易;
13、this从实例内的方法访问实例,而prototype,提供创建类的机制,不像C++或Java等其它程序语言,JavaScript并未真正支持类作为语言的具体构成要素,它使用prototype模拟类;
14、构造函数是创建JavaScript类时非常重要的一部分,它们负责构造对象实例,构造函数负责设定实例的一切事项,原型负责处理类层的一切事项;
15、Blog.prototype.toHTML=function(){…};
16、对象命名的唯一规则,只有首字母大写,但是实例的命名规则采用小写驼峰式。实例其实是一个变量;
17、面向对象编程(OOP):在程序中广泛使用对象,程序可分解成很多组彼此交互的对象集合;
18、类特性(class property)也能共享,使用prototye创建Blog.prototype.signature=“";
调用类特性只需要this.signature;
19、类特性的访问一定与实例有关;
20、利用prototype可以扩展内置的JavaScript类,是类拥有的实例方法,属于类,但能访问实例数据;
21、类方法:为类所有,但是无法访问实例特性的方法,不使用prototype对象,仅使用22、类名和点号把方法指派给类;类名是调用类对象的关键;
23、把对象的功能封装(encapsulate)至对象里,是OPP的基本概念之一,表明外部代码不应该负责对象本身可负责的工作;
24、当某个自变量未被传给函数,方法或构造函数时,在任何试图使用自变量的代码里,它的值都是null,这并不一定是坏事 ;


第11章 出错务尽 好脚本也会出错

1、不同浏览器对脚本的报错不一样,可通过多个浏览器找出错误出现的地方,总的来说Firefox非常适合去除网页脚本里所包含的缺陷;
2、凡是未被指派值的变量,会自动假设为undefined类型,变量从来不会自动设为null,其在boolean上下文中都被转换为false;
3、虽然大多数浏览器都提供了错误控制台,但并非完全准确,不能全盘相信;
4、浏览器通常产生不完全的错误信息,其都是寻找问题的线索;
5、缺少括号,打错字是常见的错误来源;
6、JavaScript代码中,引号应该成对出现;
7、当引号不是引号,使用转义符:alert(‘It\'s so exciting!'),不需要运用alert(“It's so exciting!”);
8、alert可以作为观察变量数值的窗口以及验证代码是否被运行;
9、=不等于==;
10、逻辑错误较语法错误更难处理,浏览器不提示:意图做某事,却意外地写成了另一件事情的代码;
11、凡是企图读取未定义的变量行使有意义的行为都变得完全没有意义,因而会报错;
12、注意网页里面的JavaScript代码的运行时间;
13、运行时错误(Runtime error):不会载入文档主体的问题:用户在表单里输入了脚本无法处理的数据,试图在对象创建或初始化前访问对象;
14、JavaScript三虫客:语法错误,逻辑错误,运行时错误;
15、语法错误(Syntax):由于违反JavaScript语言规则而造成的错误,表示代码不适合在JavaScript解释器中运行;
16、移除程序代码是一个绝佳的脚本显示方式:利用注释暂时禁用代码;
17、同名局部变量会掩蔽全局变量(阴影变量);局部变量在局部范围内具有优先权,阴影变量在任何情况下都应该被静止;


第12章 动态数据 贴心易感的网络应用程序

1、Ajax:使得网页的行为比较像完全成熟的应用程序,因为它们能够动态地快速下载并存储数据以及实时响应用户,却不用重新载入网页或利用浏览器的某些小手段;
2、以动态数据建造的网页称为数据驱动网页(data-driven page),这类网页只定义了等着数据填入的页面构架;
3、动态数据需要一点事前编辑工作,但是日后带来庞大的回报;
4、XML是种为任何类型的数据设计格式的标记语言;
5、XML没有定义任何标签和属性,它是一组标签与属性该如何创建和使用的规则。一切6、说明特定数据表现方式的标签与属性规范都交给各个XML应用程序;
7、现在已经有很多创建完毕的XML语言,用于解决各式各样的问题,借用这些XML语言或者创建自己专属的标记语言都非常好;
8、XHTML是遵守XML的较严格语法规则的新版HTML;

必须有结束标签;
结束标签必须有/如<br/>;
所有的属性值均以引号围起来;

9、XML对数据的外观没有概念,其专心于数据的意义;
10、XML曾经是Ajax的一部分,现在仍然是大多数Ajax应用程序的基础,其提供了数据建模的绝佳机制;
11、XML和HTML相似,遂可以透过DOM,把XML视为节点数而访问数据。小心的分离出想要的数据,然后动态的融合数据与网页;
12、在实行客户端与服务端的数据通信时,Ajax以请求(request)和响应(response)为中心概念;
13、JavaScript内置一个称为XMLHttpRequest的对象,用于发起Ajax请求并处理Ajax响应;
14、readyState:请求的代码状态0(未初始)、1(开启)、2(已传送)、3(接收中)、4(已载入);
15、status:HTTP的请求状态代码,例如404(找不到文件)或者200(OK);
16、onreadystatechange:请求状态改变时会被调用的函数引用,存储一个引用,引用于Ajax请求的状态改变时调用的自定义事件处理器——这是事件处理器就是处理响应的地方(判断Ajax是否以合格的响应结束);
17、responseText:由服务器返回的响应数据,格式为纯文本字符串;
18、responseXML:由服务器返回的响应数据,格式为XML节点树构成的对象(这两个存储服务器返回的Ajax响应数据);
19、abort()取消请求,只用在需要取消Ajax请求的时候;
20、open():准备请求,指定请求的类型,URL及其他细节;
21、send():传送请求,交给服务器处理:这两个方法合作准备Ajax请求,而后送给服务器;
22、即使是最基础的Ajax请求,也需要相当数量的JavaScript代码;
23、创建XMLHttpRequest对象的问题,在于浏览器必须提供自己的对象实现,好消息是所有浏览器使用的方法和特性都是一致的,对象的创建方式才是浏览器需要考量的差异;
24、非同步请求(asynchronous request)在后台运作,不用让脚本等待,所以几乎所有的Ajax请求都是异步的;
25、Ajax请求的类型(type)非常重要,不只反映传送到服务器的事物,也反映请求的意图;
26、GET:主要用于从服务器取得数据,而不影响服务器上的其它东西,如果需要也能透过URL传入小量数据给服务器;
27、POST:通常与传送数据到服务器有关,传送后的服务器状态通常有所改变,以响应传入的数据,例如存储数据到数据库中;
28、自定义的AjaxRequest对象减轻了制作Ajax请求的痛苦过程;
29、send(type,url,handler,postDataType,postData);
30、type 请求的类型GET或POST,url:服务器的url,数据也可以包装在url里面;
31、postDataType:被传送的数据类型;handle:用于处理响应的回调函数;
32、postData:被传送的数据;
33、自定义的请求处理函数必须为请求而设置,用于请求完毕时被调用;
34、调用AjaxRequest对象的send()方法后,有个Ajax请求被传送到服务器,网页则先行35、处理网页事物,同时服务器也在处理请求,这就是Ajax的异步,因为异步处理,网页无需暂停,用户体验不会为此停歇;
36、HTTP的请求和响应为网络浏览器所用,从网络服务器上获取HTML网页。Ajax的请求与响应与HTTP的非常相似,但有几项关键差异;Ajax版随时可能发生,不见得牵涉到HTML数据的递送,Ajax最大的好处之一,就是它能请求任何类型的数据;
37、Ajax的请求和响应为实时发生,通常不会干涉网页的使用性,当网页上的一小块需要更新时,用户不用停下来等着整个网页重新载入,那块区域可于“背景”载入,用户可以继续浏览网页其它部分并与之交互;
38、GET和POST的主要区别在于服务器是否经历状态改变,例如存储数据到数据库;
自定义的AjaxRequest的角色是标准对象XMLHttpRequest的“外包装”,用于简化Ajax的使用;
39、交互式网页就从请求对象开始;
40、客户端脚本使用自定义的回调函数处理Ajax请求的响应;
41、AjaxRequest对象的方法具有对Ajax响应数据的访问权。getResponseText():以纯文本的格式取得Ajax响应里地访问与getResponseXML():以结构XML代码的格式取得Ajax响应里的数据;
42、Ajax请求在state市4(loaded)且status是200(OK)时,表示完全成功;
43、handleRequest()函数只有在同时达成这两个状态时起身工作;
44、暂时禁用按钮是一个绝佳的方案,而后于handleRequest()函数中启用;
45、PHP是种可在服务器上执行任务的脚本语言;
46、大多数时候,除了最简单的请求,所有Ajax请求都牵涉到服务器端接受来自客服端的数据,然后根据数据而行动;
47、运行PHP需要调校一下你的网络服务器;
48、URL-encoded格式:每段数据需要有自己的名称和值,中间插入(=),每对名称/值之间则用&区隔;
49、代码之间的共享使得网页更加精简。 

 
 



小结:

《Head First JavaScript》是一本入门书,语言通俗易懂,幽默风趣,很多部分比较偏基础,但是又不失细节,本书以实例为指导来说明JavaScript的一个个部分,确实能增强初学者对JavaScript的作用的理解,总的来说看完本书,我感觉收获还是很大的,笔记只是本书的很少的一部分,如果对JavaScript有一定了解,但是感觉又不是很清楚的同学,推荐大家阅读一下,一定会很有收获的。
本人也是前端的初学者,之后会慢慢再跟大家分享自己学习过程中看的书,做的笔记,期待跟大家一起进步,本文只是个人笔记,如果有错误的地方,希望大家能够指出,希望跟大家一起探讨交流。

打开App,阅读手记
45人推荐
发表评论
随时随地看视频慕课网APP

热门评论

喜欢headfirst系列的书,比起纯文字的好多了。

少年 很赞哦 本人认真的研读了

嗯,到位的很

查看全部评论