有元素可继承:
visibility和cursor
内联元素和块级元素可继承:
letter-spacing
word-spacing
white-space
line-height
color
font
font-family
font-size
font-style
font-variant
font-weight
text-decoration
text-transform
direction
块级元素可继承
:
text-indent和text-align
列表元素可继承:
list-style
list-style-type
list-style-position
list-style-image
表格元素可继承:
border-collapse
不可继承:
display
margin
border
padding
background
height
min-height
max-height
width
min-width
max-width
overflow
position
left
right
top
bottom
z-index
float
clear
table-layout
vertical-align
page-break-after
page-bread-before
unicode-bidi
切图网(qietu.com)专业从事web前端开发的公司,专注we前端开发,响应式布局,webapp手机端网页制作,微信html5页面制作,bootstrap布局等,关注用户体验。
现在用户面前的WEB页面,内容无非就是文字、图片、视频、音频这四大方面。而这些内容要呈现在用户眼前,最最基础的一种互联网语言,就是HTML(HyperText Markup Language)标记语言。所有千变万化、眼花缭乱、酷炫精彩的内容,都离不开HTML标签的汗马功劳。下面小白就总结一下自学后的一些基础的HTML知识点。
HTML中的标签元素一般分为三大类,它们分别是:块级元素、行内元素、行内块级元素。下面总结一下这几类元素的特点及应用。
01 块级元素
特点:
① 独占一行、从上到下排列
② 可直接控制宽度、高度及盒子模型的CSS属性(width 、height、padding 等属性值)
③ 在不单独设置宽度的情况下,块级元素的宽度(width属性)继承父元素
④ 在不单独设置高度的情况下,块级元素的高度(height属性)靠自己的基因(它本身内容的高度)
块级元素从我的理解来说,就是一个大框框,用来框住其它元素不要乱跑乱窜的,只能在一定范围内活动。所以,它通常会用来进来大的结构搭建。
常用的块级元素:
标题类 | <h1></h1> | <h2></h2> |
<h3></h3> | <h4></h4> | |
<h5></h5> | <h6></h6> | |
列表类 | <ol></ol> | <ul></ul> |
<li></li> | <dl></dl> | |
<dt></dt> | <dd></dd> | |
普通类 | <div></div> | <p></p> |
</hr> | <center></center> | |
<pre></pre> | ||
表格类 | <table></table> | |
表单类 | <form></form> |
02 行内元素
特点:
① 元素与元素之间会自动排列成一行,遇到空间不够自动换行
② 默认高度和宽度(width、height)属性与它们的内容有关,无内容那么它本身也就是虚无。
③ 行内元素不支持padding、margin的上下调动(它们就是紧挨着不离不弃、除非用外部手部强制拆散它们)
行内元素一般用来修饰点缀内容而用,语义化比较强,用来加强代码的可读性。
常用的行内元素:
<a></a> | <b></b> | <br></br> |
<span></span> | <strong></strong> | |
<i></i> | <em> </em> | <sub> </sub> |
<sup> </sup> |
03 行内块元素
特点:
从这个名字就可以看出来,它是一个结合体,块级元素和行内元素的结合体。它具备二者共有的一些特点,使用非常频繁。
① 元素具有块级元素的属性(width、height等属性),可以对其直接控制
② 虽然有宽和高,但是他并不会霸道地独占一行,它具有行内元素的“亲情属性”,会自动排列挨在一起。
③ 行内块元素支持padding、margin的上下调动
<img> </img> | <input /> | <select> </select> |
<textarea> </textarea> | <label> </label> | <button> </button> |
欢迎大佬提点指正
JavaScript 在编程语言界是个特殊种类,它和其他编程语言很不一样,JavaScript 可以在运行的时候动态地改变某个变量的类型。
比如你永远也没法想到像isTimeout这样一个变量可以存在多少种类型,除了布尔值true和false,它还可能是undefined、1和0、一个时间戳,甚至一个对象。
如果代码跑异常,打开浏览器,开始断点调试,发现InfoList这个变量第一次被赋值的时候是个数组:
[{name: 'test1', value: '11'}, {name: 'test2', value: '22'}]
过了一会竟然变成了一个对象:
{test1:'11', test2: '22'}
除了变量可以在运行时被赋值为任何类型以外,JavaScript 中也能实现继承,但它不像 Java、C++、C# 这些编程语言一样基于类来实现继承,而是基于原型进行继承。
这是因为 JavaScript 中有个特殊的存在:对象。每个对象还都拥有一个原型对象,并可以从中继承方法和属性。
提到对象和原型,有如下问题:
在 JavaScript 中,对象由一组或多组的属性和值组成:
{
key1: value1,
key2: value2,
key3: value3,
}
在 JavaScript 中,对象的用途很是广泛,因为它的值既可以是原始类型(number、string、boolean、null、undefined、bigint和symbol),还可以是对象和函数。
不管是对象,还是函数和数组,它们都是Object的实例,也就是说在 JavaScript 中,除了原始类型以外,其余都是对象。
这也就解答了问题1:JavaScript 的函数怎么也是个对象?
在 JavaScript 中,函数也是一种特殊的对象,它同样拥有属性和值。所有的函数会有一个特别的属性prototype,该属性的值是一个对象,这个对象便是我们常说的“原型对象”。
我们可以在控制台打印一下这个属性:
function Person(name) {
this.name = name;
}
console.log(Person.prototype);
打印结果显示为:
可以看到,该原型对象有两个属性:constructor和proto。
到这里,我们仿佛看到疑惑 “2:proto和prototype到底是啥关系?”的答案要出现了。在 JavaScript 中,proto属性指向对象的原型对象,对于函数来说,它的原型对象便是prototype。函数的原型对象prototype有以下特点:
我们可以用这样一张图来描述prototype、proto和constructor三个属性的关系:
从这个图中,我们可以找到这样的关系:
对象之所以使用广泛,是因为对象的属性值可以为任意类型。因此,属性的值同样可以为另外一个对象,这意味着 JavaScript 可以这么做:通过将对象 A 的proto属性赋值为对象 B,即:
A.__proto__ = B
此时使用A.proto便可以访问 B 的属性和方法。
这样,JavaScript 可以在两个对象之间创建一个关联,使得一个对象可以访问另一个对象的属性和方法,从而实现了继承;
以Person为例,当我们使用new Person()创建对象时,JavaScript 就会创建构造函数Person的实例,比如这里我们创建了一个叫“zhangsan”的Person:
var zhangsan = new Person("zhangsan");
上述这段代码在运行时,JavaScript 引擎通过将Person的原型对象prototype赋值给实例对象zhangsan的proto属性,实现了zhangsan对Person的继承,即执行了以下代码:
//JavaScript 引擎执行了以下代码
var zhangsan = {};
zhangsan.__proto__ = Person.prototype;
Person.call(zhangsan, "zhangsan");
我们来打印一下zhangsan实例:
console.log(zhangsan)
结果如下图所示:
可以看到,zhangsan作为Person的实例对象,它的proto指向了Person的原型对象,即Person.prototype。
这时,我们再补充下上图中的关系:
从这幅图中,我们可以清晰地看到构造函数和constructor属性、原型对象(prototype)和proto、实例对象之间的关系,这是很多容易混淆。根据这张图,我们可以得到以下的关系:
那么现在,关于proto和prototype的关系,我们可以得到这样的答案:
所以一个对象可通过proto访问原型对象上的属性和方法,而该原型同样也可通过proto访问它的原型对象,这样我们就在实例和原型之间构造了一条原型链。红色线条所示:
当 JavaScript 试图访问一个对象的属性时,会基于原型链进行查找。查找的过程是这样的:
我们可以通过一个具体的例子,来表示基于原型链的对象属性的访问过程,在该例子中我们构建了一条对象的原型链,并进行属性值的访问:
var o = {a: 1, b: 2}; // 让我们假设我们有一个对象 o, 其有自己的属性 a 和 b:
o.__proto__ = {b: 3, c: 4}; // o 的原型 o.__proto__有属性 b 和 c:
当我们在获取属性值的时候,就会触发原型链的查找:
console.log(o.a); // o.a => 1
console.log(o.b); // o.b => 2
console.log(o.c); // o.c => o.__proto__.c => 4
console.log(o.d); // o.c => o.__proto__.d => o.__proto__.__proto__ == null => undefined
综上,整个原型链如下:
{a:1, b:2} ---> {b:3, c:4} ---> null, // 这就是原型链的末尾,即 null
可以看到,当我们对对象进行属性值的获取时,会触发该对象的原型链查找过程。
既然 JavaScript 中会通过遍历原型链来访问对象的属性,那么我们可以通过原型链的方式进行继承。
也就是说,可以通过原型链去访问原型对象上的属性和方法,我们不需要在创建对象的时候给该对象重新赋值/添加方法。比如,我们调用lily.toString()时,JavaScript 引擎会进行以下操作:
由于通过原型链进行属性的查找,需要层层遍历各个原型对象,此时可能会带来性能问题:
因此,我们在设计对象的时候,需要注意代码中原型链的长度。当原型链过长时,可以选择进行分解,来避免可能带来的性能问题。
除了通过原型链的方式实现 JavaScript 继承,JavaScript 中实现继承的方式还包括经典继承(盗用构造函数)、组合继承、原型式继承、寄生式继承,等等。
function Parent(name) {
// 私有属性,不共享
this.name = name;
}
// 需要复用、共享的方法定义在父类原型上
Parent.prototype.speak = function() {
console.log("hello");
};
function Child(name) {
Parent.call(this, name);
}
// 继承方法
Child.prototype = new Parent();
组合继承模式通过将共享属性定义在父类原型上、将私有属性通过构造函数赋值的方式,实现了按需共享对象和方法,是 JavaScript 中最常用的继承模式。
虽然在继承的实现方式上有很多种,但实际上都离不开原型对象和原型链的内容,因此掌握proto和prototype、对象的继承等这些知识,是我们实现各种继承方式的前提条件。
关于 JavaScript 的原型和继承,常常会在我们面试题中出现。随着 ES6/ES7 等新语法糖的出现,可能更倾向于使用class/extends等语法来编写代码,原型继承等概念逐渐变淡。
其次JavaScript 的设计在本质上依然没有变化,依然是基于原型来实现继承的。如果不了解这些内容,可能在我们遇到一些超出自己认知范围的内容时,很容易束手无策。
*请认真填写需求信息,我们会在24小时内与您取得联系。