注册
登录

您现在的位置是:首页 > 学无止境

javascript注意事项

木木彡82 2009-07-09 15:55:00 2928人围观
1、关于引用//创建数组var items = new Array("one","two","three");//创建数组的一个引用var itemsRef = items;//将一个元素添加到数组中items.puth("fo...

1、关于引用

 

2、关于变量的类型

(1)、变量类型检查

变量----------------------------------typeof 变量-----------------------------------变量.constructor

{an : "object"}----------------------object------------------------------------------Object

["an", "array"]-----------------------object------------------------------------------Array

function (){}-------------------------function----------------------------------------Function

"a string"----------------------------string-------------------------------------------String

55-------------------------------------number----------------------------------------Number

true-----------------------------------boolean----------------------------------------Boolean

new User()-------------------------object-------------------------------------------User

当函数无明确返回值时,返回的也是值undefined。

Null类型只有一个专用值null。alert(null == undefined);输出true,尽管他们相等,但含义不同,undefined是声明了变量但未对其初始化时赋予该变量的值,null则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是null。

NaN是一个特殊值,表示非数(Not a Number),通常出现在类型转换失败时,NaN不能用于算术计算,而且它与自身不相等,alert(NaN == NaN);将返回FALSE,可以用isNaN()函数来判断。

(2)、类型强制转换

可用如下3个函数来进行类型强制转换:

Boolean(value)------------把给定的值转换成Boolean型

当要转换的值是至少有一个字符的字符串、非0数字或对象时,Boolean()函数将返回TRUE;如果该值是空字符串、数字0、undefined、null时,将返回FALSE。

String(value)---------------把给定的值转换成字符串

String()方法可以把任何值转换成字符串。强制转换成字符串和调用toString()方法的唯一不同之处在于,对null和undefined值强制类型转换可以生成字符串而不引发错误。

Number(value)------------把给定的值转换成数字(可以是整数或浮点数)

(3)、instanceof运算符

instanceof运算符与typeof运算符类似,用于识别正在处理的对象的类型。与typeof方法不同的是,instanceof方法要求开发者明确的确认对象为某特定的类型。

 

3、关于作用域

javascript中,所有属于全局作用域的变量其实都是window对象的属性

如果变量没有显式定义,那么它就是全局定义的。

 

4、关于闭包

 

5、关于上下文对象

上下文对象是通过this变量体现的,这个变量永远指向当前代码所处的对象中。

 

6、关于javascript面向对象

在javascript中,任何函数都可以被实例化成一个对象。

 

7、关于公有方法

通过对象的prototype属性,这个属性包含了一个对象,该对象可以作为所有新副本的基引用。

 

8、关于私有方法

 

9、关于特权方法

动态生成的特权方法:


10、关于原型式继承

User是对User对象构造函数的引用。new Person()使用Person构造函数创建了一个新的Person对象,然后把User构造函数的原型置为这个操作的结果。也就是说,每当你new User()时,得到新User对象都会带有Person对象所有的方法,如同通过操作new Person()得到的一样。

 

11、关于类式继承

它提供了一个简单的方法,把函数与构造函数的原型关联起来。之所以有效,是因为所有的构造函数本身都是函数,所以能获得method这个新方法。

这一函数可以用于提供简单的单对象继承,它的代码主要围绕在任意对象方法中调用this.uber('methodName')为中心,并在让这个uber方法去执行它要覆盖的父对象的方法。

这是.method()函数的增强版,可以用于从单一父对象获取多个函数。如果用在多个父对象上就能获得可用的多对象继承。

示例:

 

12、关于命名空间

实际上,javascript里并不存在命名空间的概念,但考虑到javascript的所有对象都有自己的属性,属性又可以包含对象,这样就能创造一些和其他语言里的命名空间神似的东西了。

 

13、关于几点编码习惯

(1)、变量声明

程序里所有的变量都必须在使用前声明。虽然javascript并没有明确要求这么做,但不声明会导致变量的实际作用域不好理解。

(2)、!=和==对!==和===

在javascript中,null、undefined是相等的(==),而0、""、false之间也是两两相等的(==)""

(3)、代码块与大括号

不应该使用单行的代码块。比如在判断语句后面即使只跟着一条语句,也应该保留大括号,while和for也是如此。虽然对单行语句不使用大括号是javascript提供的巨大便利,但这可能导致其他人的误解。

(4)、分号

javascript里如果每个语句单独占一行,那语句后面的分号不是必需的。在未压缩的代码里不用分号当然没什么问题,但在去除换行符以压缩代码后就可能导致问题了。要避免这样的问题,你应该时时记住,在所有语句后面加上分号。

 

14、关于DOM文档里的nodeType

nodeType=1:匹配HTML或XML中的大部分元素。比如,<li>、<a>、<p>、<body>等元素都有一个值为1的nodeType

nodeType=3:匹配文档内的的所有文本块。当使用previousSibling和nextSibling来遍历DOM结构时,你会经常碰到元素内和元素间的文本块。

nodeType=9:匹配文档的根元素。比如在HTML文档内,它是<html>元素。

 

15、关于两个DOM方法

getElementById("every"):该方法只能运行在document对象下

getElementsByTagName("li"):该方法能运行在任何对象下,找出该元素下的所有标签名为li的后代元素,并返回一个 NodeList。该结构跟普通的javascript数组非常相似,但一个重要的不同之处在于:它并不支 持.push()、.pop()、.shift()等javascript数组的常用方法。

 

16、关于判断DOM何时加载完毕

以下是检查HTML DOM是否可用的几个要点:

(1)、document:你需要知道DOM文档是否已经加载。若能足够快的检查,运气好的话你能看到undefined。

(2)、document.getElementsByTagName和document.getElementById:频繁使用这两个函数检查文档,当存在这些函数则表明已完成加载。

(3)、document.body:作为额外补充,检查<body>元素是否已经完全加载。

 

17、关于通过类(class)的值查找元素

 

18、关于XPath

css3选择器和XPath表达式比较

目标----------------------------------------------css3-----------------------------------------XPath

所有元素-----------------------------------------*----------------------------------------------//*

所有<p>元素------------------------------------p---------------------------------------------//p

所有子元素--------------------------------------p > *-----------------------------------------//p/*

由ID获取元素-----------------------------------#foo-------------------------------------------//*[@id='foo']

由类获取元素-----------------------------------.foo-------------------------------------------//*[contains(@class,'foo')]

由属性获取元素--------------------------------*[title]----------------------------------------//*[@tilte]

<p>的第一个子元素----------------------------p>*:first-child------------------------------//p/*[0]

所有拥有子元素的<p>-------------------------不支持---------------------------------------//p[a]

下一个元素--------------------------------------p + *------------------------------------------//p/下一兄弟元素::*[0]

 

19、关于获取元素文本内容

 

20、关于innerHTML的几点说明

(1)、IE返回的元素字符都是大写的,如果你想保持一致性可能会感到失望

(2)、innerHTML作为一个只能用在HTMLDOM文档的元素中的属性,若在XMLDOM文档中使用的话只会返回null值

 

21、关于创建DOM元素

createElementNS() 方法与 createElement() 方法 相似,只是它创建的 Element 节点除了具有指定的名称外,还具有指定的命名空间。只有使用命名空间的 XML 文档才会使用该方法。

 

22、关于删除DOM元素

 

23、关于事件对象(event object)

IE使用一个独立的全局事件对象(它可以在全局变量属性window.event中找到),而其他浏览器则使用独立的包含事件对象的参数传递。

事件对象拥有许多你可以在事件监听函数中使用的属性:

target: 触发事件的元素(在IE中,target被srcElement取代了)。

type: 被触发的事件(例如,click)。

button: 被按下的鼠标按钮。0代表左键,1代表中键,2代表右键(详见关于35)。

keyCode/data/charCode: 被按下的键的字符编码。W3C规范使用data,可是它并没有获得广泛的支持。相反大多数浏览器都是用charCode,而keyCode是IE的实现。幸好所有的浏览器都能理解keyCode,这意味着你现在可以使用它(详见关于36)。

shiftKey/ctrlKey/altKey: 一个布尔值-----如果shift、ctrl、alt键分别的被按下则返回true。

 

24、关于取消事件冒泡

希望事件发生在它的目标而非它的父元素上

 

25、关于浏览器的默认行为

浏览器的默认行为可以归纳为没有明确指令而浏览器自动执行的行为。例如点击<a>元素将重定向到它的href属性上的URL

 

26、关于绑定事件监听函数

(1)、传统方式

优点:非常简单和稳定,可以确保在不同的浏览器中运作一致;处理事件时,this关键字引用的事当前元素

缺点:只会在事件冒泡中运行,而非捕获和冒泡;一个元素一次只能绑定一个事件处理函数;事件对象参数仅非IE浏览器可用

(2)、W3C方式

addEventListener有3个参数:事件的名称(比如click)、处理事件的函数、一个启用或禁用事件捕获的布尔标记。

优点:该方法同时支持事件处理的捕获和冒泡阶段。取决于addEventListener最后的参数设置:false(冒泡)或true(捕获); 在事件处理函数内部,this关键字引用当前元素;事件对象总是可以通过处理函数的第一个参数获取;可以绑定多个事件而不会覆盖先前绑定的事件。

缺点:不支持IE,必须使用IE的attachEvent函数代替

(3)、IE方式

优点:可以绑定多个事件

缺点:IE仅支持事件捕获的冒泡阶段;监听函数内的this关键字指向了window对象而不是当前对象;事件对象仅存在于window.event参数中;事件必须以ontype的形式命名;仅有IE可用

 

27、关于确保链接不依赖于javascript

当点击链接是发生GET请求,提交表单时则发生POST请求。规范指出GET请求不应有破坏性的副作用(比如删除一条消息),如果通过链接可以删除、编辑或者修改任何用户的数据,你应该使用表单来进行。

 

28、关于访问式样信息

javascript要求你在设置任何几何属性时必须明确尺寸单位(例如设置高度,必须使用px单位)。同时,任何几何属性都会返回表示元素式样的字符串而非数值(例如是100px而非100)

 

29、关于元素定位

(1)、静态定位:这是元素定位的默认方式。当元素是静态定位时,top和left属性无效。

(2)、相对定位:与静态定位相似,但是设置top或left属性会引起元素相对于它的原始(静态)位置进行偏移。

(3)、绝对定位:绝对定位的元素会相对于它的第一个非静态定位的祖先元素而展示。如果没有这样的祖先元素,则相对于整个文档。

(4)、固定定位:固定定位把元素相对于浏览器窗口而定位。例如设置元素的top和left为0会使它显示在浏览器左上角,它完全忽略浏览器滚动条的拖动,一直会出现在用户的视野。

 

30、关于获取元素位置

offsetLeft和offsetTop这两个属性分别是元素在offsetParent上下文中的水平和垂直偏移量。

 

31、关于元素的可见性

CSS有两种不同的方式可以有效的隐藏元素。

visibility属性在切换元素可见性的同时会保持元素普通流的属性的相关影响。它 有两个值:visible(默认的)和hidden(不可见的)。假设一小段文本包含在<b>标签内,同时<b>的 visibility设置为hidden,那么结果就是文本内有一块空白留白,它的尺寸刚好等于被包裹文本的原有尺寸。即虽然不显示,但是其在页面的位置 还是被其占据。

display属性可以是inline(比如<b>和<span>的标签是inline的,它们都 遵循文本的普通流动)、block(比如<p>和<div>的标签是block的,它们都打破文本的普通流动)或none(它完 全从文档中隐藏了元素)。设置元素display属性的结果跟从文档中删除了该元素的情形看起来一样,只是该元素还可以迅速的切换回文档的视觉中来。

 

32、关于表单验证

(1)、验证必填

 

(2)、验证匹配

 

33、关于AJAX

 

34、关于DOM函数的说明

(1)、appendChild(nodeToAppend): 这是一个可用来为元素追加子节点的函数。如果需要追加节点已存在于文档中,那么它会从原有位置移动到当前元素上。appendChild函数必须在你所期望追加的元素上调用。

(2)、cloneNode(true|false): 该函数是一种通过克隆已有的节点为开发者简化代码的方法,而克隆出来的节点也能够插入到DOM中去。因为一个普通的insertBefore或者appendChild会把文档中的DOM节点移开,但cloneNode函数能够克隆新的节点而保持原有节点的位置。该函数有一个值是true或者false的参数。如果参数是true,节点及其内部的所有东西都会克隆,如果是false,则只有节点本身被克隆。

(3)、insertBefore(nodeToInsert, nodeToInsertBefore): 这是一个用来在文档的任意地方插入DOM节点的函数。该函数必须在你希望插入到前面的元素的父元素上调用。该函数带有两个参数,一个是你希望插入到DOM中的节点,另一个是需要插入前面位置的DOM节点。

(4)、removeChild(nodeToRemove): 这个函数用来删除文档的节点。该函数必须在你希望删除节点的父元素上调用。

(5)、replaceChild(nodeToInsert, nodeToReplace): 这个函数是删除一个节点并在原地插入另外一个节点的替代方法。该函数必须在你需要替换的节点的父元素上调用。该函数带两个参数:你希望插入到DOM的节点和希望替换的节点。

 

35、关于鼠标属性

鼠标属性仅在鼠标相关的事件(比如click、mousedown、mouseup、mouseover、mousemove和mouseout)发生时才存在于事件对象中。

(1)、clientX/clientY: 这两个属性包含相对于窗口的鼠标光标的x和y坐标。

(2)、pageX/pageY: 这两个属性包含相对于呈现文档的鼠标光标的x和y坐标(例如,如果你向下滚动文档,得到的数字将不会等于clientX/clientY属性所包含的值)。它们在IE中无效,要在IE中获取光标的位置,你必须使用clientX/clientY属性并加上当前的滚动偏移值。

(3)、layerX/layerY和offsetX/offsetY: 这些属性包含相对于事件目标元素的鼠标光标的x和y坐标。layerX/layerY属性可用在基于Mozilla的浏览器和safari,而offsetX/offsetY则可用在opear和IE中。

(4)、button: 这个属性是表示当前点击(仅可用于click、mousedown和mouseup事件)的鼠标键的数字。

点击--------------------------------IE---------------------------------W3C

左键---------------------------------1-----------------------------------0

右键---------------------------------2-----------------------------------2

中键---------------------------------4-----------------------------------1

在IE中,返回3代表左键和右键同时按下,返回7代表左键、中键和右键3个键同时被按下。

(5)、relatedTarget: 这个事件对象包含一个鼠标刚离开的元素的引用。除此之外,还可用在这样的场合:需要使用mouseover/mouseout,而且必须知道鼠标所处,或者即将进入的元素。

 

36、关于键盘属性

键盘属性一般只在键盘相关的事件(比如keydown、keyup和keypress)发生时才存在于事件对象中。除了ctrlKey和shiftKey属性,它们可以在鼠标事件中存在(这就允许ctrl+click一个元素)。而其余场合,你可以假定这些返回值并不存在或不确定。

(1)、ctrlKey: 该属性返回一个布尔值,表示键盘的Ctrl键是否被按住。该属性可存在于键盘和鼠标事件中。

(2)、keyCode: 这个属性包含一个键盘响应键位的数字。某些键位(比如pageup和home键)的可用性并不能确定,但一般来说,其他的键位均工作稳定。

键位------------------------------------------------------------代码

退格键(Backspace)---------------------------------------------8

制表键(Tab)-----------------------------------------------------9

回车键(Enter)---------------------------------------------------13

空格键(Space)--------------------------------------------------32

左箭头键(Left arrow)-------------------------------------------37

上箭头键(Up arrow)----------------------------------------------38

右箭头键(Rigth arrow)-------------------------------------------39

下箭头键(Down arrow)-------------------------------------------40

0-9-----------------------------------------------------------48~57

A-Z-----------------------------------------------------------65~90

(3)、shiftKey: 该属性返回一个布尔值,表示键盘的Shift键是否被按住。该属性可存在于键盘和鼠标事件中。

 

37、关于页面事件

(1)、beforeunload: 在事件处理函数内,如果返回的是字符串,那么字符串就会显示在一个确认窗口中,询问用户是否希望离开当前页面。

(2)、error: error事件在javascript代码发生错误时触发,它无需传递事件对象参数,而包含一条已发生错误的解释信息。

(3)、resize: 在用户重置浏览器窗口时触发。当用户调整浏览器窗口的尺寸时,resize事件仅在完成重置的事件触发一次,而不是每一步都会触发。

(4)、scroll: 于用户在浏览器窗口内移动文档的位置时触发。这会在键盘敲击(比如箭头、翻页或者空格键)或使用滚动条时触发。

(5)、unload: 这个事件在用户离开当前页(可以是点击链接、后退键甚至是关闭浏览器窗口)时触发。阻止默认行为并不会在此事件中生效。

 

38、关于键盘事件

keydown/keypress

keydown事件是键盘敲击时触发的第一个键盘事件。如果用户继续按住键位,keydown事件会持续进行。keypress是keydown事件的同义事件,它们的表现完全一致,只有一个例外。如果需要阻止按键的默认行为,你必须使用keypress事件。

 

39、关于表单事件

表单事件主要处理<form><input><select><button><textarea>元素

(1)、select: select事件在用户使用鼠标于输入框内选择不同区块的文本时触发。

(2)、change: change事件在用户改变了输入元素(包括<select>和<textarea>元素)的值时触发。该事件仅在用户已经离开了元素,使其失去焦点时触发。

 

40、关于CSS-DOM

css-dom技术简单来说就是读取和设置style对象的各种属性。style属性最大的不足是无法通过它来提取到外部CSS设置的样式信息。可以使用jquery等框架,例如jquery中的css()方法无论是外部css导入,还是直接拼接在HTML元素里(内联),css()方法都可以获取到属性style里的其他属性值。

 

41、关于变量命名规则

(1)可以是字母(大小写均可)、美元符$以及下划线_,但是首字符不能是数字。
(2)后续的字符由字母、数字、下划线、美元符组成。

(3)最好不要用保留字做变量名称。
(4)变量名称区分大小写。
注意:在函数中定义变量时,没写var则是全局变量。

 

42、关于String对象

可以显式或者隐式的创建String对象,隐式创建如下:

显式创建如下:

显式与隐式创建String对象的唯一真正区别是,如果你要重复的使用同样的字符串,显式的创建字符串有更高的效率。显式的创建String对象还有助于防止JavaScript解释器混淆数字和字符串。

 

43、关于Array对象

JavaScript的数组索引不仅可以用数字,也可以用字符串来充当。例如:

但是要注意,如果数组中有字符串的索引,那么在使用数组的length属性时可能会得不到正确的结果。例如上例中最后如果alert(my.length)的话,返回的结果是1,并不是我们期望的3,这是因为数组的length属性返回比数组中最后一个数字项索引大1的索引,而上例中最后一个数字项索引是0,所以返回的结果是1。也就是说数组的length属性并不一定等于数组中元素的个数。

 

44、关于父节点和子节点

(1)、从父节点到子节点

如果想更改P段落的文本值,你可能认为应该像下面那样设置:

可是,这并不起作用,因为P段落是一个element节点。如果你想更改段落内部的文本,就需要访问它内部的文本节点:

firstChild属性是个简便用法,每个元素都可以有任意数量的子节点,可以通过childNodes属性列出来:

[1]、childNodes是该元素所有第一层子节点的列表----并不包括向下更深的层次。

[2]、可以通过数组计数器或item()方法访问当前元素的子元素。

[3]、简便用法yourElement.firstChild和yourElement.lastChild是yourElement.childNodes[0]和yourElement.childNodes[yourElement.childNodes.length-1]的简化版本,可以使访问更快捷一些。

[4]、可以通过方法hasChildNodes()检查一个元素是否有子节点,它会返回一个布尔值。

(2)、从子节点到父节点

通过parentNode属性,可以从子节点回到父节点。

 

45、关于兄弟节点之间

可以通过一个节点的previousSibling和nextSibling属性访问同一级别上的不同子节点。

可以分别获得li item2和li item4。

注意,这个是IE ONLY。在其余浏览器中下一个和上一个兄弟并不是LI元素,而是将换行符作为内容的文本节点。

如果当前对象是父节点的最后一个子节点,那么nextSibling就会是undefined.

 

46、关于获取和修改元素属性

有2种方式来获取和修改元素属性:

(1)、以对象属性的方式来获取和设置元素的属性:

这种方法不支持用户自定义属性,如P元素的isp属性。但是class属性是个例外,因为class在ECMAScript中是一个保留字,在JavaScript中,它不能被作为变量名、属性名或者函数名,所以相应的属性名就变成了className。

(2)、通过getAttribute和setAttribute方法:

这种方法更贴近高级编程语言,而且支持用户自定义属性。但IE在setAttribute上有个很大的问题:当你使用它时,变更并不会总是正确的反映出来。所以如果打算支持IE,最好尽可能使用属性方式,即第一种方法。

 

47、关于一元运算符

(1)、delete: delete运算符删除对以前定义的对象属性或方法的引用,但不能删除开发者未定义的属性或方法。

(2)、void: void运算符对任何值都返回undefined,该运算符通常用于避免输出不应该输出的值。

<a href="javascript:window.open('about:blank');">click</a>这种写法可能和你想要的结果不同,应该采用下句的写法:

<a href="javascript:void(window.open('about:blank'));">click</a>

(3)、一元加法和一元减法

一元加法本质上对数字无任何影响,但却会把字符串转换成数字。

一元减法就是对数值求负,也会把字符串转换成近似的数字,此外还会对该值求负。

 

48、关于关系运算符

上例因为两个运算数都是字符串,所以比较的是它们的字符代码("2"的字符代码是50,"3"的字符代码是51)。

上例字符串"23"将被转换成数字23,然后与数字3进行比较。无论何时比较一个数字和字符串,ECMAScript都会把字符串转换成数字,然后按照数字顺序比较它们。

上例因为字母"a"不能转换成有效的数字。不过,如果对它调用parseInt()方法,返回的是NaN。根据规则,任何包含NaN的关系运算都要返回false。

 

49、关于函数重载

JavaScript中的函数不能重载,虽然可以在同一个作用域中定义两个相同名字的函数,而不会引发错误,但真正使用的是后一个函数。但是JavaScript可以通过arguments对象模拟重载。如下:

上例中的sayHi()函数arguments[0]表示第一个参数,以此类推,因此,无需明确命名参数。还可用arguments.length检测参数个数。

PS: JavaScript不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数都可以接受任意个数的参数,而不会引发任何错误。任何遗漏的参数都会以undefined传递给函数,多余的参数将忽略。

 

50、关于call()和apply()方法以及caller和callee

call()和apply()它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别:

apply(thisArg, argArray);call(thisArg[,arg1,arg2…]);

即所有函数内部的this指针都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的。

(1)、call()方法是实现继承的好方法。call()方法第一个参数用作this对象,其他参数都直接传递给函数自身。如果call的第一个参数是null或undefined,被调用的function将被传入全局对像作为this。全局对象就是window对象。

在这个例子中,函数sayColor()在对象外定义,即使它不属于任何对象,也可以引用关键字this。对象obj的color属性等于red。调用call()方法时,第一个参数是obj,说明应该赋予sayColor()函数中的this关键字值是obj。第二和第三个参数是字符串,它们与sayColor()函数中的参数prefix和suffix匹配。

(2)、apply()方法有2个参数,用作this的对象和要传递给函数的参数的数组。

第一个参数与call()方法相同。第二个参数是由两个字符串组成的数组,与sayColor()的参数prefix和suffix匹配。

只有超类中的参数顺序与子类中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。此外,还可以使用call()方法。

(3)、caller返回一个对函数的引用,该函数调用了当前函数。

对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。

(4)、callee返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。

callee 属性的初始值就是正被执行的 Function 对象。callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名
函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是形参长度,由此可以判断调用时形参长度是否和实参长度一致。

 

 

 

 

 

 

 

 

 

 

文章评论

  • 登录后评论

点击排行