欢迎旅行者到此一游
【前端学习笔记】关于前端的一些基础。
ShiinaAiiko.NO.00004·2019年08月13日 · 文章

HTML 语义类标签

语义类标签是什么,使用它有什么好处?

1、语义类标签对开发者更为友好,使用语义类标签增强了可读性,即便是在没有CSS的时候,开发者也能够清晰地看出网页的结构,也更为便于团队的开发和维护。

2、除了对人类友好之外,语义类标签也十分适宜机器阅读。它的文字表现力丰富,更适合搜索引擎检索(SEO),也可以让搜索引擎爬虫更好地获取到更多有效信息,有效提升网页的搜索量,并且语义类还可以支持读屏软件,根据文章可以自动生成目录等等。

“用对”比“不用”好,“不用”比“用错”好


作为自然语言延伸的语义类标签

em

em标签告诉浏览器把其中的文本表示为强调的内容。

对于所有浏览器来说,这意味着要把这段文字用斜体来显示。

和strong是不同的产物


作为标题摘要的语义类标签

h1-h6

h1-h6是最基本的标题,它们表示了文章中不同层级的标题


hgroup

在hgroup中的h1-h6被视为同一标题的不同组成部分


作为整体结构的语义类标签

正确使用整体结构类的语义标签,可以让页面对机器更友好

header 头部标签

nav 导航链接标签

footer 尾部标签

aside 侧边栏标签

section 标签定义文档中的节(section、区段),比如章节、页眉、页脚或文档中的其他部分

article 独立的自包含内容。一般来说,article会有标题部分( 包含在header内 ),有时也会包含footer。

address 一个给机器阅读的地址,而是表示“文章(作者)的联系方式”


<body>
    <header>
        <nav>
            ……
        </nav>
    </header>
    <aside>
        <nav>
            ……
        </nav>
    </aside>
    <article>
        <header>……</header>
        <section>……</section>
        <section>……</section>
        <section>……</section>
        <footer>……</footer>
    </article>
    <article>
        ……
    </article>
    <article>
        ……
    </article>
    <section>……</section>
    <section>……</section>
    <section>……</section>
    <footer>
        <address>……</address>
    </footer>
</body>


语义类标签一览

aside 表示侧边栏、导航性质的工具内容

article 文字主体部分、有明确的独立性

hgroup 标题组

h1~h6 各级标题

abbr 表示缩写

hr 横向分隔线

p 表示段落

strong 加粗、表示很重要

blockquote 表示段落级引述内容

q 表示行内的引述内容

cite 表示引述的作品名

time 日期、方便机器阅读

figure 插入文章中的内容、不限于图片、代码、表格等等

figcaption 内容标题

dfn 包裹被定义的名词

nav 导航目录

ol 有序列表

ul 无序列表

pre 预先排版、不需要浏览器换行

samp 计算机程序的示例输出

code 定义计算机代码

samll 补充评论

s 划线 错误内容、主要用于电商打折前的价格

i 斜体 读的变调

b 黑体 关键字

u 下划线 避免歧义的标记

data 和time类似、利于机器阅读

var 变量、多用于计算机和数学领域

kbd 用户输入、键盘按键居多

sub 下标

sup 上标

bdo,bdi 语言书写方向(从右到左、或者从左到右)

mark 高亮

wbr 可以换行的位置

menu ul的变体、用于功能菜单

dl,dd,dt 对一些术语的定义

main 整个页面只出现一个、页面的主要内容、特殊的div


JavaScript 关于类型

七种数据类型一览

运行时类型是代码实际执行过程中我们用到的类型。所有的类型数据都会属于7个类型之一。从变量、参数、返回值到表达式中间结果,任何JavaScript代码运行过程中产生的数据,都具有运行时类型。


原始数据类型

Boolean

含义:表示逻辑上的真或假

取值:true 和 false


Null

含义:表示值为空

取值:null

注意:

1、null是关键字。

2、可以通过将变量的值赋值为null将其清空


Undeffined

含义:表示未初始化

取值:undefined

注意:

1、undefined是运行时创建的全局变量。

2、没有为函数传参,该函数值为undefined,或函数没有显示返回,则返回值为undefined


Number

含义:表示数字

取值:-(2^63-1) ~ 2^63-1

注意:

1、符合IEEE754-2008规定的双精度浮点数规则。

2、既可以表示整数,又可以表示浮点数。

3、还引入了+Infinity,-Infinity和NaN。

4、只有一个整数又两种表示方法:+0 和 -0 。

5、非整数不能通过==或===来判断,但是可以采用Math.abs(0.1+0.2-0.3)<=Number.EPSILON


String

含义:表示文本数据

取值:最大长度2^53-1

注意:

1、采用UTF16

2、处理非BMP(超出U+0000 - U+FFFF范围)的字符需要格外小心


Symbol

含义:表示独一无二的值

取值:通过Symbol函数生成的、如:let s = Symbol()

注意:

1、主要为了表征对象属性名的唯一性,基本上类似String类型

2、Symbol函数前不能使用new命令

3、Symbol函数可接受字符串参数作为Symbol实例的描述

4、Symbol值不能与其他类型的值进行运算

演示代码:

    // ES6 引入了一种新的原始数据类型Symbol, 表示独一无二的值。 它是 JavaScript 语言的第七种数据类型, 前六种是: undefined、 null、 布尔值( Boolean)、 字符串( String)、 数值( Number)、 对象( Object)。
    // 例子:

    var teacher = {
        [Symbol('name')]: '忠彬老师',
        [Symbol('description')]: '讲课讲得好'
    }
    var dabinge = {
        [Symbol('name')]: '大彬哥',
        [Symbol('description')]: '帅'
    }
    var target = {};
    Object.assign(target, teacher, dabinge);
    console.log(target);
    // console.log(target, teacher, dabinge);


    // 这个在书写插件和库的时候很重要, 因为经常涉及到选项或者参数合并, symbal很好的解决了这个问题。
    // 解决问题的场景:

    var teacher = {
        name: '忠彬老师',
        description: '讲课讲得好'
    }
    var dabinge = {
        name: '大彬哥',
        description: '帅'
    }
    var target = {}; //结合两个对象复制到一个新对象
    Object.assign(target, teacher, dabinge);
    console.log(target);
    // console.log(target, teacher, dabinge);



Object类型

含义:表示一组属性的集合

取值:

1、字面量、如:var person = {name: 'tom' , age: '18'};

2、Object函数、如:var obj = Object(value); 、参数的若是原始类型的值则返回其包装对象、参数若是对象则返回其本身

3、Object构造函数、如:var obj = new Object(); 、与Object函数的规则类型,但语义不同、Object函数表示类型转换、Object构造函数表示生成一个新的对象。

4、Object.create方发、如:const me = Object.create(person); 、指定原型对象和属性、返回一个新的对象

注意:

1、对象有两种属性:数据属性、访问器属性

3、对象的属性名可以是String类型、也可以是Symbol类型


相关问题

  • 为什么有的编程规范要求用void 0代替undefined?

因为JavaScript的代码undefined是一个变量,而并非是一个关键字,这是JavaScript语言公认的设计失误之一,所以,我们为了避免无意中被篡改,我建议使用 void 0 来获取undefined值。


  • 字符串有最大长度吗?

有、最大长度为2^53-1


  • 0.1 + 0.2不是等于0.3么?为什么JavaScript里不是这样的?

根据浮点数的定义,非整数的Number类型无法用 ==(===也不行) 来比较:

  console.log( 0.1 + 0.2 == 0.3);

这里输出的结果是false,说明两边不相等的,这是浮点运算的特点,浮点数运算的精度问题导致等式左右的结果并不是严格相等,而是相差了个微小的值。


所以实际上,这里错误的不是结论,而是比较的方法,正确的比较方法是使用JavaScript提供的最小精度值:

  console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);

检查等式左右两边差的绝对值是否小于最小精度,才是正确的比较浮点数的方法。这段代码结果就是 true 了。


  • ES6新加入的Symbol是个什么东西?

Symbol 是 ES6 中引入的新类型,它是一切非字符串的对象key的集合,在ES6规范中,整个对象系统被用Symbol 重塑。

表示独一无二的值。


  • 为什么给对象添加的方法能用在基本类型上?
    Symbol.prototype.hello = () => console.log("hello");
    var a = Symbol("a");
    console.log(typeof a); //symbol,a并非对象
    a.hello(); //hello,有效

运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。


类型转换

讲完了基本类型,我们来介绍一个现象:类型转换。

因为JS是弱类型语言,所以类型转换发生非常频繁,大部分我们熟悉的运算都会先进行类型转换。大部分类型转换符合人类的直觉,但是如果我们不去理解类型转换的严格定义,很容易造成一些代码中的判断失误。

其中最为臭名昭著的是JS中的“ == ”运算,因为试图实现跨类型的比较,它的规则复杂到几乎没人可以记住。

这里我们当然也不打算讲解==的规则,它属于设计失误,并非语言中有价值的部分,很多实践中推荐禁止使用“ ==”,而要求程序员进行显式地类型转换后,用 === 比较。

其它运算,如加减乘除大于小于,也都会涉及类型转换。幸好的是,实际上大部分类型转换规则是非常简单的,如下表所示:

在这个里面,较为复杂的部分是Number和String之间的转换,以及对象跟基本类型之间的转换。我们分别来看一看这几种转换的规则。


StringToNumber

字符串到数字的类型转换,存在一个语法结构,类型转换支持十进制、二进制、八进制和十六进制,比如:

30;

0b111;

0o13;

0xFF。


此外,JavaScript支持的字符串语法还包括正负号科学计数法,可以使用大写或者小写的e来表示:


1e3;

-1e-2。


需要注意的是,parseInt 和 parseFloat 并不使用这个转换,所以支持的语法跟这里不尽相同。

在不传入第二个参数的情况下,parseInt只支持16进制前缀“0x”,而且会忽略非数字字符,也不支持科学计数法。

在一些古老的浏览器环境中,parseInt还支持0开头的数字作为8进制前缀,这是很多错误的来源。所以在任何环境下,都建议传入parseInt的第二个参数,而parseFloat则直接把原字符串作为十进制来解析,它不会引入任何的其他进制。

多数情况下,Number 是比 parseInt 和 parseFloat 更好的选择。


NumberToString


在较小的范围内,数字到字符串的转换是完全符合你直觉的十进制表示。当Number绝对值较大或者较小时,字符串表示则是使用科学计数法表示的。这个算法细节繁多,我们从感性的角度认识,它其实就是保证了产生的字符串不会过长。

具体的算法,你可以去参考JavaScript的语言标准。由于这个部分内容,我觉得在日常开发中很少用到,所以这里我就不去详细地讲解了。


装箱转换

每一种基本类型Number、String、Boolean、Symbol在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。

前文提到,全局的 Symbol 函数无法使用 new 来调用,但我们仍可以利用装箱机制来得到一个 Symbol 对象,我们可以利用一个函数的call方法来强迫产生装箱。

我们定义一个函数,函数里面只有return this,然后我们调用函数的call方法到一个Symbol类型的值上,这样就会产生一个symbolObject。

我们可以用console.log看一下这个东西的type of,它的值是object,我们使用symbolObject instanceof 可以看到,它是Symbol这个类的实例,我们找它的constructor也是等于Symbol的,所以我们无论从哪个角度看,它都是Symbol装箱过的对象:

var symbolObject = (function(){ return this; }).call(Symbol("a"));

console.log(typeof symbolObject); //object
console.log(symbolObject instanceof Symbol); //true
console.log(symbolObject.constructor == Symbol); //true


装箱机制会频繁产生临时对象,在一些对性能要求较高的场景下,我们应该尽量避免对基本类型做装箱转换。

使用内置的 Object 函数,我们可以在JavaScript代码中显式调用装箱能力。

var symbolObject = Object(Symbol("a"));

console.log(typeof symbolObject); //object
console.log(symbolObject instanceof Symbol); //true
console.log(symbolObject.constructor == Symbol); //true


每一类装箱对象皆有私有的 Class 属性,这些属性可以用 Object.prototype.toString 获取:

var symbolObject = Object(Symbol("a"));
console.log(Object.prototype.toString.call(symbolObject)); //[object Symbol]


在 JavaScript 中,没有任何方法可以更改私有的 Class 属性,因此Object.prototype.toString 是可以准确识别对象对应的基本类型的方法,它比 instanceof 更加准确。

但需要注意的是,call本身会产生装箱操作,所以需要配合 typeof 来区分基本类型还是对象类型。


拆箱转换

在JavaScript标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型的转换(即,拆箱转换)。

对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。

拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。


var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}

o * 2
// valueOf
// toString
// TypeError


我们定义了一个对象o,o有valueOf和toString两个方法,这两个方法都返回一个对象,然后我们进行o*2这个运算的时候,你会看见先执行了valueOf,接下来是toString,最后抛出了一个TypeError,这就说明了这个拆箱转换失败了。

到 String 的拆箱转换会优先调用 toString。我们把刚才的运算从o*2换成 o + “”,那么你会看到调用顺序就变了。

var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}

o + ""
// toString
// valueOf
// TypeError

在 ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为。

var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}

o[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}


console.log(o + "")
// toPrimitive
// hello


七种规范类型

List 和 Record: 用于描述函数传参过程。

Set:主要用于解释字符集等。

Completion Record:用于描述异常、跳出等语句执行过程。

Reference:用于描述对象属性访问、delete等。

Property Descriptor:用于描述对象的属性。

Lexical Environment 和 Environment Record:用于描述变量和作用域。

Data Block:用于描述二进制数据。


JavaScript对象:关于面向对象

什么是面向对象?

从人类的认知角度来说,对象应该是下列事物之一:

  1. 一个可以触摸或者可以看见的东西;
  2. 人的智力可以理解的东西;
  3. 可以指导思考或行动(进行想象或施加动作)的东西。


设计者也利用各种不同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java等流行的编程语言。

而 JavaScript 早年却选择了一个更为冷门的方式:原型(关于原型,我在下一篇文章会重点介绍,这里你留个印象就可以了)。这是我在前面说它不合群的原因之一。

然而很不幸,因为一些公司政治原因,JavaScript推出之时受管理层之命被要求模仿Java,所以,JavaScript创始人Brendan Eich在“原型运行时”的基础上引入了new、this等语言特性,使之“看起来更像Java”。

JavaScript 对象的特征

  • 对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。


对象具有唯一标识的内存地址、所以对象是具有唯一性的。

var o1 = { a: 1 };
var o2 = { a: 1 };
console.log(o1 == o2); // false
  • 对象有状态:对象具有状态,同一对象可能处于不同状态之下。
  • 对象具有行为:即对象的状态,可能因为它的行为产生变迁。


关于对象的第二个和第三个特征“状态和行为”,不同语言会使用不同的术语来抽象描述它们,比如C++中称它们为“成员变量”和“成员函数”,Java中则称它们为“属性”和“方法”。

在 JavaScript中,将状态和行为统一抽象为“属性”,考虑到 JavaScript 中将函数设计成一种特殊对象,所以 JavaScript中的行为和状态都能用属性来抽象。

下面这段代码中,o是对象,d是一个属性,而函数f也是一个属性,尽管写法不太相同,但是对JavaScript来说,d和f就是两个普通属性。

    var o = { 
        d: 1,
        f() {
            console.log(this.d);
        }    
    };

JavaScript中对象独有的特色是:对象具有高度的动态性,这是因为JavaScript赋予了使用者在运行时为对象添改状态和行为的能力。


JavaScript对象的两类属性

第一类属性,数据属性。

它比较接近于其它语言的属性概念。数据属性具有四个特征。

  • value:就是属性的值。
  • writable:决定属性能否被赋值。
  • enumerable:决定for in能否枚举该属性。
  • configurable:决定该属性能否被删除或者改变特征值。


定义属性的代码会产生数据属性,其中的writable、enumerable、configurable都默认为true。

可以使用内置函数 Object.getOwnPropertyDescripter来查看

如果我们要想改变属性的特征,或者定义访问器属性,我们可以使用Object.defineProperty。

如代码演示:

    var o = { a: 1 };
    Object.defineProperty(o, "b", {value: 2, writable: false, enumerable: false, configurable: true});
    //a和b都是数据属性,但特征值变化了
    Object.getOwnPropertyDescriptor(o,"a"); // {value: 1, writable: true, enumerable: true, configurable: true}
    Object.getOwnPropertyDescriptor(o,"b"); // {value: 2, writable: false, enumerable: false, configurable: true}
    o.b = 3;
	console.log(o.b); // 2
	// 因为writable特征为false,所以我们重新对b赋值,b的值不会发生变化。


第二类属性是访问器(getter/setter)属性。

它也有四个特征。

  • getter:函数或undefined,在取属性值时被调用。
  • setter:函数或undefined,在设置属性值时被调用。
  • enumerable:决定for in能否枚举该属性。
  • configurable:决定该属性能否被删除或者改变特征值。


在创建对象时,也可以使用 get 和 set 关键字来创建访问器属性,代码如下所示:

    var o = { get a() { return 1 } };

    console.log(o.a); // 1

访问器属性跟数据属性不同,每次访问属性都会执行getter或者setter函数。这里我们的getter函数返回了1,所以o.a每次都得到1。


实际上JavaScript 对象的运行时是一个“属性的集合”,属性以字符串或者Symbol为key,以数据属性特征值或者访问器属性特征值为value。

如以上面的对象o为例:

“a”是key。

{writable:true,value:1,configurable:true,enumerable:true}是value。



未完待续......

未完待续......


(内容总结于源自winter《重学前端》)

重庆市
多云
Windows
like
dislike
1
202
作者:ShiinaAiiko.NO.00004
时间:2019.08.13 05:16
comments0
ShiinaAiiko.NO.00004欢迎旅行者到此一游
推荐
从未发布过哦
ShiinaAiiko.NO.00004欢迎旅行者到此一游