myBlog


  • Home

  • Archives

普通类型和对象的区别

Posted on 2019-02-24

JavaScript 一共有七种数据类型,其中六种 string、number、boolean、undefined、symbol、null 称为普通类型(原始类型),object(对象)称为复杂类型(引用类型)。
当我们打开浏览器时(以Chrome为例),Chrome 打开即占用一定大小的内存,当我们打开多个页面时,Chrome 给每个网页分配一定数量的内存,这些内存要分给页面渲染器、网络模块、浏览器外壳和 JS 引擎(V8引擎),JS 引擎将内存分为代码区和数据区,我们只研究数据区。

1. 两种类型在内存中的形式

数据区分为 Stack(栈内存) 和 Heap(堆内存),普通类型的数据直接存在 Stack 里,复杂类型的数据是把 Heap 地址存在 Stack 里,如图:

上图中,变量 a、b、c 都是普通类型的数据,它们的数据都存在 Stack 里,数字使用64位存储,字符使用16位(32位)。而 o1 和 o2 为复杂类型,它们的 Satck 存储数据的 Heap 地址,真正的数据存储在地址所对应的 Heap 中。

为了更清楚的理解普通类型和复杂类型在内中的作用机制,可以通过面试题的几个代码举例。

面试题1:

1
2
3
4
var a = 1
var b = a
b = 2
请问 a 显示是几?

首先,浏览器通过声明提升,先声明变量 a 和 b ,都是 undefined,然后再将 1 赋给 a,此时 a = 1,再将 a 的值 赋给 b,此时 b = 1,在内存中可表示为:

执行第三行代码时,将 2 赋给 b,也就是说 b 的 Stack 里的 1,变成了2,在内存中可表示为:

所以,a 的值到最后还是 1。

面试题2:

1
2
3
4
var a = {name: 'a'}
var b = a
b = {name: 'b'}
请问现在 a.name 是多少?

第一行代码将一个对象赋给 a,此时 a 的 Stack 里边存的是该对象数据所在 Heap 的地址,Heap 里边存储着对应地址的具体数据。
第二行代码将 a 的 Stack 里边的内容复制一份,赋给了 b,也就是放到了 b 的 Stack中,此时a和b的 Stack 共同指向同一个 Heap 地址,在内存中可表示为:

第三行代码将一个新的对象 {name: 'b'} 赋给了b,因为{name: 'b'}是一个新的对象值,它在 Heap 中会有一个新的地址,所以 b 的 Stack 的值也会是一个指向新 Heap 的地址,在内存中可表示为:

所以,a.name 的值是 'a'。

面试题3:

1
2
3
4
var a = {name: 'a'}
var b = a
b.name = 'b'
请问现在 a.name 是多少?

前两行代码同面试题2一样,a和b的 Stack 共同指向同一个 Heap 地址,当运行到第三行代码时,b.name 访问的是 heap 中该对象的key:'name' ,并且将 'b' 赋值给了所对应的 value,也就是改变了该键值对的值,在内存中可表示为:

所以,a.name 的值是 'b'。

面试题4:

1
2
3
4
var a = {name: 'a'}
var b = a
b = null
请问现在 a 是什么?

前两行代码同之前一样,a和b的 Stack 共同指向同一个 Heap 地址,当运行到第三行代码时,将 null 赋给了 b,由于 null 是普通类型的值,所以这个值会保存在 b 的 Stack 中,而 a 和 Heap 都没有变化。在内存中可表示为:

所以,a 的值还是{name: 'a'}。

面试题5:

1
2
3
4
5
6
var a = { n:1 }
var b = a
a.x = a = { n:2 }

alert(a.x) // -->undefined
alert(b.x) // -->[object Object]

执行第一行和第二行代码之后,a 和 b 的 Stack 中的地址都指向 Heap 中的{ n:1 }(ADD:369),在执行第三行代码时,浏览器先从左往右阅读代码,此时 a.x 中的 a 和 = 后边的 a 的值相等(ADD:369)。

然后浏览器从右往左计算(赋值),先执行a = { n:2 },将 { n:2 } 赋给了中间的a,此时,a 的 Stack 中的地址因为指向新赋予的对象已经改变为(ADD:567)。

再计算a.x = a ,而a.x 中 a 中的地址仍然是之前保存 { n:1 } 的地址,所以这一步计算在之前的 Heap 里,添加了一个新的键值对,key 是 x,值是存有 { n:2 } 的 Heap 地址。

最终的结果为:

所以,a.x 的结果为undefined,b.x 的结果为[object Object]。在代码中要尽量避免a.x = a = { n: 2} 这种写法。

普通类型在栈内存中存储,复杂类型是在 Stack 内存中存储 Heap 地址,在地址所对应的 Heap 地址中存储该类型,通过引用建立关系。值类型之间传递的是值,引用类型之间传递的是地址(引用)。值类型作为函数的参数传递的是值,引用类型作为函数的参数传递的是地址(引用)。

2.深拷贝与浅拷贝

1
2
3
4
5
var a = 1
var b = a
b = 2 //这个时候改变 b
a 完全不受 b 的影响
那么我们就说这是一个深拷贝

对于简单类型的数据来说,赋值就是深拷贝。
对于复杂类型的数据(对象)来说,才要区分浅拷贝和深拷贝。

1
2
3
4
var a = {name: 'a'}
var b = a
b.name = 'b'
a.name === 'b' // true

上述代码对 b 操作后,a 也变了,所以是浅拷贝。
对 Heap 内存进行完全的拷贝,称为深拷贝。

3. GC 垃圾回收机制

在浏览器给 JS 分配的内存中,如果 Heap 中的某个对象没有被任何其他对象或者变量进行引用,则会被浏览器视为垃圾,删除该对象,回收该内存地址。

4. 为什么简单类型也可以调用方法

在我们使用 JavaScript 的时候,通过 var 声明一个普通类型的时候,发现也可以调用相关的方法,如图所示。

但普通类型并不具有方法,这是因为当我们执行n.toString() 的时候,JS 会在内存中创建一个临时的对象 temp = new Numer(n),temp 是 n 的复杂类型的封装,实际上n.toString() 等于 temp.toString(),然后把temp.toString() 的值作为n.toString() 的值返回,然后再消除掉temp 这个临时对象。同理,其他普通类型的的方法也都是这样。

JavaScript 数据类型转换

Posted on 2019-02-22

JavaScript 一共有七种数据类型,分别是:string、number、boolean、object、symbol、null、undefined,它们在一定情况下可以相互转换。

1. 转换为string

  • toString()
    每个对象都有一个 toString() 方法,返回该对象的字符串形式(该方法不能转换null 和 undefined)。
  • String()
    String函数可以将任意类型的值转化成字符串(包括Symbol类型),转换规则如下。
    • 数值:转为相应的字符串。
    • 字符串:转换后还是原来的值。
    • 布尔值:true转为字符串"true",false转为字符串"false"。
    • undefined:转为字符串"undefined"。
    • null:转为字符串"null"。
      String()方法在转换Object类型时,无论Object中的键值为何,只会转换成字符串 "[object Object]"。
  • 被转换值 + ’’(空字符串) 推荐使用

    需要注意的是这种方法不能转换Symbol类型的值。

2. 转换为Boolean

  • Boolean()
  • !! 推荐使用
    !运算符表示取反,会将数据转换为其Boolean值相反的值,两次取反操作即可得到数据自身的Boolean值。

    falsy(虚值)是在 Boolean 上下文中已认定可转换为「假」的值。常见的五个虚值有:0,NaN,undefined,null,''或""。

3. 转换为Number

  • Number()
    使用Number函数,可以将任意类型的值转化成数值。

    需要注意的是,Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。当Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。
  • parseInt()
    parseInt方法用于将字符串转为整数。字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分(Numer方法则会返回NaN)。如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。如果字符串以0x或0X开头,parseInt会将其按照十六进制数解析。无法转换科学记数法表示的数字和自动会被JS转化为科学记数法的数字。如果转换小数,则会自动忽略小数部分。

    parseInt方法还可以接受第二个参数(2到36之间,超出范围返回NaN ,如果第二个参数是0、undefined和null,则直接忽略。),表示被解析的值的进制,返回该值对应的十进制数。默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制(ES5)。
  • parseFloat
    parseFloat方法用于将一个字符串转为浮点数, 如果字符串符合科学计数法,则会进行相应的转换,会将空字符串、布尔值和null转为NaN。

    如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。
  • -0 推荐使用
    -0 方法在转换数字字符串时可以将其转换为数字,返回值基本都等同于Number 方法。
  • +
    和+0方法类似,返回值基本都等同于Number 方法。

javaScript-数据类型

Posted on 2019-02-22

数据类型

  1. number
    • 整数和浮点数:
      JavaScript 内部,所有数字都是以64位浮点数形式储存 ,浮点数不是精确的值
      1 1.1 .1
    • 科学记数法:
      小数点前的数字多于21位和小数点后的零多于5个,JavaScript 会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示。 1.34e2 123e-2
    • 二进制:有前缀0b或0B的数值:0b11
    • 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
    • 十六进制:有前缀0x或0X的数值。
      • 正零和负零:JavaScript 内部实际上存在2个0:一个是+0,一个是-0,区别就是64位浮点数表示法的符号位不同。它们是等价的。
        +0或-0当作分母返回的值是不相等的:+Infinity !== -Infinity
    • NaN:NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),数据类型依然属于Number,NaN不等于任何值,包括它本身。
    • Infinity:Infinity表示“无穷”,用来表示两种场景。一种是一个正的数值太大(大于等于2的1024次方),或一个负的数值太小(小于等于2的-1075),无法表示;另一种是非0数值除以0,得到Infinity。
      Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。
    • parseInt()
      • 用于将字符串转为整数
        字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。如果字符串以0x或0X开头,parseInt会将其按照十六进制数解析。无法转换科学记数法表示的数字和自动会被JS转化为科学记数法的数字。
      • 进制转换
        parseInt()方法还可以接受第二个参数(2到36之间,超出范围返回NaN ,如果第二个参数是0、undefined和null,则直接忽略。),表示被解析的值的进制,返回该值对应的十进制数。默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制(ES5)。
        如果字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值。如果最高位无法转换,则直接返回NaN。
    • parseFloat()
      • parseFloat方法用于将一个字符串转为浮点数, 如果字符串符合科学计数法,则会进行相应的转换。
      • parseFloat会将空字符串、布尔值和Null转为NaN。
    • isNaN()
      • isNaN方法可以用来判断一个值是否为NaN, 只对数值有效。
    • isFinite()
      • isFinite方法返回一个布尔值,表示某个值是否为正常的数值。
        除了Infinity、-Infinity、NaN和undefined这几个值会返回false,isFinite对于其他的数值都会返回true。
  2. string

    • 零个或多个排在一起的字符,放在单引号或双引号之中。字符串默认只能写在一行内,分成多行将会报错。如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠,后边只能跟换行符,不能跟其他字符。

      1
      2
      3
      4
      5
      6
      7
      var longString = 'Long \
      long \
      long \
      string';

      longString
      // "Long long long string"

      连接运算符(+)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行。

      1
      2
      3
      4
      var longString = 'Long '
      + 'long '
      + 'long '
      + 'string';
    • 转义
      反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。在非特殊字符前面使用反斜杠,则反斜杠会被省略。
      \0 :null(\u0000)
      \b :后退键(\u0008)
      \f: 换页符(\u000C)
      \n :换行符(\u000A)
      \r: 回车键(\u000D)
      \t :制表符(\u0009)
      \v :垂直制表符(\u000B)
      \' :单引号(\u0027)
      \" :双引号(\u0022)
      \\ :反斜杠(\u005C)

    • 字符串可以使用数组的方括号运算符,用来返回某个位置的字符,只能读取,无法进行删改操作,如果方括号中的数字超过字符串的长度,或者方括号中不是数字,则返回undefined。 string.length属性返回字符串的长度。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var s = 'hello';
      s[0] // "h"
      s[1] // "e"
      s[4] // "o"

      // 直接对字符串使用方括号运算符
      'hello'[1] // "e"

      var s = 'hello';
      s.length // 5
    • Base64 转码(不适合非 ASCII 码的字符)
      btoa():任意值转为 Base64 编码。
      atob():Base64 编码转为原来的值。
      要将非ASCII码字符转为Base64编码,必须中间插入一个转码环节

  3. null
    null表示空值,即该处的值现在为空。调用函数时,某个参数未设置任何值,这时就可以传入null,表示该参数为空。null在运算中可以自动转为0。

    1
    2
    Number(null) // 0
    5 + null // 5
  4. undefined
    undefined表示“未定义”,应用场景:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 变量声明了,但没有赋值
    var i;
    i // undefined

    // 调用函数时,应该提供的参数没有提供,该参数等于 undefined
    function f(x) {
    return x;
    }
    f() // undefined

    // 对象没有赋值的属性
    var o = new Object();
    o.p // undefined

    // 函数没有返回值时,默认返回 undefined
    function f() {}
    f() // undefined
  5. boolean
    布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示,只有这两个值,通常用于程序流程的控制。在JS中,undefined null false 0 NaN ""都会被转为false。其他都转为true,包括空数组和空对象。
    a && b 在 a 和 b 都为 true 时,取值为 true;否则为 false。
    a || b 在 a 和 b 都为 false 时,取值为 false;否则为 true。

  6. symbol(ES6)
  7. object

    • 对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。

      1
      2
      3
      4
      var obj = {
      foo: 'Hello',
      bar: 'World'
      };
    • 对象的所有键名都是字符串,JS会自动将键名转换为字符转形式。如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。

    • 对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用。

      1
      2
      3
      4
      5
      6
      7
      var obj = {
      p: function (x) {
      return 2 * x;
      }
      };

      obj.p(1) // 2

      上文中对象 obj 的属性p 的值为一个函数,可以直接调用该函数。

    • 如果属性的值还是一个对象,就形成了链式引用。

      1
      2
      3
      4
      5
      var o1 = {};
      var o2 = { bar: 'hello' };

      o1.foo = o2;
      o1.foo.bar // "hello"
    • 属性的操作

      • 属性的读取
        一种是使用点运算符, 一种是使用方括号运算符。如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理,如果key的值是变量,则只能使用方括号运算符,且不能加引号。 数值键名不能使用点运算符。

        1
        2
        3
        4
        5
        6
        var obj = {
        p: 'Hello World'
        };

        obj.p // "Hello World"
        obj['p'] // "Hello World"
      • 属性的赋值
        点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。

        1
        2
        3
        4
        var obj = {};

        obj.foo = 'Hello';
        obj['bar'] = 'World';
      • 属性的查看
        查看一个对象本身的所有属性,可以使用Object.keys方法。

      • 属性的删除:delete 命令

        1
        2
        3
        4
        5
        6
        var obj = { p: 1 };
        Object.keys(obj) // ["p"]

        delete obj.p // true
        obj.p // undefined
        Object.keys(obj) // []

        如果只想删除一个键值对的 value 保留key,可以使用obj.p = undefined 的方法操作。
        delete命令只能删除对象本身的属性,无法删除继承的属性。

      • 属性是否存在:in 运算符
        in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true,否则返回false。它的左边是一个字符串,表示属性名,右边是一个对象。

        1
        2
        3
        var obj = { p: 1 };
        'p' in obj // true
        'toString' in obj // true
      • 属性的遍历:for…in 循环
        for…in循环用来遍历一个对象的全部属性。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        var obj = {a: 1, b: 2, c: 3};

        for (var i in obj) {
        console.log('键名:', i);
        console.log('键值:', obj[i]);
        }
        // 键名: a
        // 键值: 1
        // 键名: b
        // 键值: 2
        // 键名: c
        // 键值: 3

杂七杂八的笔记

Posted on 2019-02-21

获取页面宽高(JS)

1
2
var pageWidth = dociment.documentElement.clientWidth
var pageHeight = dociment.documentElement.clientHeight

ul ol 去除默认样式(CSS)

1
2
3
ul,ol {
list-style: none;
}

解决相邻元素添加样式布局抖动(CSS)

设置透明边框
border: 2px solid transparent;

添加阴影、元素缩放(CSS)

1
2
box-shadow: 0 0 3px rgba(0,0,0,0.5);
transform: scale(1.2);

图片使用flex布局后拉伸解决

1
2
3
4
.images{
display: flex;
align-items: flex-start;
}

设置变形过度时间

transition: all 0.2s;

offset()

可以阻止浏览器合并前后两个紧挨的事件。

1
2
3
4
5
6
7
$slides.css({transform:'translateX(-1600px)'})
.one('transitionend', function(){
$slides.hide()
.offset()
$slides.css({transform:'translateX(-400px)'})
.show()
}

上述代码如果直接写,浏览器会忽略掉.hide(),中间加offset()则可以实现CSS 的先隐藏后显示。

解决触屏设备上页面整体跟着手指滑动(未解决)

禁掉页面的滚动条即可

1
2
3
body {
overflow: hidden;
}

保存canvas图片到本地

1
2
3
4
5
6
7
8
9
downLoad.onclick = function () {
var url = canvas.toDataURL('image/png')
var a = document.createElement('a')
document.body.appendChild(a)
a.href = url
a.download = 'myPicture'
a.target = '_blank'
a.click()
}

浮动元素内文本不换行

1
2
3
.topNavBar .subMenu > li {
white-space: nowrap;
}

判断节点类型 MDN

nodeType 属性可用来区分不同类型的节点,比如 元素, 文本 和 注释。
语法

1
var type = node.nodeType;

常用:
Node.ELEMENT_NODE 一个 元素 节点,例如 \<p> 和 \<div>。
Node.TEXT_NODE Element 或者 Attr 中实际的文字

获取标签中href的两种方式

x 为监听到到的事件,a = x.currentTarget

  1. a.href 获取到的地址是带有 http 协议以及域名的地址(浏览器处理过的)。
  2. a.getAttribute('href') 获取直接地址。

页面元素距离页面(窗口)顶端的数值

  1. element.offsetTop 距离页面顶端的举例,数值这个是常量
    1
    2
    let rect = element.getBoundingClientRect()
    rect.top //举例当前视窗顶端的举例,这是个会随窗口滚动变化的变量。

页面内滚动到指定元素

  1. 设置锚点,但是窗口顶部如果有跟随浮动元素,会有遮挡。
  2. 精确滚动到某个位置,可以解决锚点方法存在的问题。
    1
    2
    3
    4
    5
    6
    7
    aTags[i].onclick = function(event) {
    event.preventDefault()
    let a = event.currentTarget
    let href = a.getAttribute('href')
    let element = document.querySelector(href)
    let top = element.offsetTop
    window.scroll(0, top - 80) //80为浮动窗口的高度

目前已知常用 API

  1. setTimeout:计时器
  2. window.onscroll:监听屏幕滚动事件。
  3. window.scrollY:获取窗口滚动高度。
  4. documen.querySelecorAll(‘选择器’):接受一个选择器,返回选择器对应的所有元素,获取到的内容是一个数组
  5. documen.querySelecor:获取第一个元素。
  6. element.onmouseenter:当鼠标进入一个元素会触发一个事件。
  7. element.onmouseleave:当鼠标离开一个元素会触发一个事件。
  8. event.preventDefault:阻止一个事件的默认事件。
  9. event.currentTarget:返回绑定事件的元素。
  10. event.target:返回触发事件的元素
  11. a.getAttribute(‘href’):获取用户在标签上写的原文。
  12. a.href:获取浏览器处理过的的带有 http 协议以及域名的地址。
  13. window.scrollTo(x, y):滚动页面到某个位置。
  14. element.offsetTop:获取元素举例页面顶端的位置(常量)。

tween.js库

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.3.0/Tween.js"></script> //cdnjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function animate(time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
requestAnimationFrame(animate)

var coords = {y: 0 }
var tween = new TWEEN.Tween(coords)
.to({y: 200 }, 1000)
.easing(TWEEN.Easing.Quadratic.InOut)
.onUpdate(function() {

})
.start()

函数节流

1
2
3
4
5
6
7
8
9
10
11
12
13
var fn = function() {}
var cd = false
button.onclick = function() {
if(!cd) {
//cd 中
} else {
fn()
cd = true
var timerId = setTimeout(() => {
cd = false
},3000)
}
}

函数防抖

1
2
3
4
5
6
7
8
9
10
11
var fn = function() {}
var timerId = null
button.onclick = function(){
if(timerId) {
window.clearTimeout(timerId)
}
timeId = setTimeout(() => {
fn()
timerId = null
},5000)
}

AJAX

1
2
3
4
5
6
7
8
9
10
11
12
var request = new XMLHttpRequest()
request.open('GET', '/XXXX')
request.readystatechange = function() {
if(request.readyState === 4) {
console.log('请求完成')
if(request.response.status >= 200 && request.response.status < 300) {
console.log('请求成功')
}else{
}
}
}
request.send()

this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//1 fn()
this => window

//2 obj.fn()
this => obj

//3 fn.call(xx)
this => xx

//4 fn.apply(xx)
this => xx

//5 fn.bind(xx)
this => xx

//6 new Fn()
this => 新的对象

//7 fn = () => {}
this => 外边的对象

深拷贝

  1. 递归
  2. 判断类型
  3. 检查循环引用(环)
  4. 不可能拷贝原型 __proto__(浪费内存)

正则实现 tirm()

1
2
3
var trim = function() {
return string.replace(/^\s+|\s+$/g, '')
}

数组去重

  1. hash
  2. set
  3. WeakMap

从 10 - 100 中取 10 个随机数组成数组

1
2
3
4
5
6
7
8
9
10
11
const randomArr = (a, b) => {
let arr = []
a = Math.min(a)
b = Math.max(b)

for (let i = 0; i < 10; i++) {
let n = Math.random() * (b - a) + a
let num = Math.ceil(n)
arr.push(num)
}
}

样式分离

HTML:内容
CSS:样式
JS:行为
如果不样式分离,会使代码杂乱无章,不好区分代码的逻辑结构,也不容易维护。

阻止事件冒泡

1
event.stopPropagation()

在冒泡过程中,可以向上级元素添加事件。(常见bug)

1
2
3
4
5
6
7
8
9
10
$(button).on('click', function() {
console.log('1')
$(popover).show()
$(document).one('click', function() {
console.log('2')
$(popover).hide()
})
})
//1
//2

上边代码中,在点击button按钮时,第二个ciick事件会在点击的一瞬间添加到document元素上,同时因为浏览器默认事件冒泡,第二个事件会在第一个事件执行完毕后立即执行(几乎没有间隔)。

解决方法之一:setTimeout(fn(){},0)

1
2
3
4
5
6
7
8
9
$(clicked).on('click', function() {
console.log('1')
$(popover).show()
setTimeout(function(){
$(document).one('click', function() {
$(popover).hide()
})
},0)
})

CSS布局

Posted on 2019-02-17

利用 float 左右或左中右布局

CSS中块级元素,每一个块占用一行,从上往下依次流动,如果需要让块级元素实现左右布局,一个方法是给每个元素添加 float 属性。
如图,给 c1,c2,c3 添加 float 属性,使其左右依次排列。

如图所示三个 div 实现了左右依次浮动,但是它们的父元素却因为没高度而塌陷了。因为块级元素的高度由其内部文档流元素的高度总和决定,添加 float 属性后,这三个 div 脱离了文档流,所以其父元素就没有高度了。要解决这个问题,可以给浮动元素的父元素上边添加一个叫做 clearfix 的类。

1
2
3
4
5
6
7
```
.clearfix::after {
content: '';
display: block;
clear: both;
}
```

上述代码通过伪类 :after 在父级元素后边添加内容,来实现清除浮动从而实现左右布局。

上图中有三个 div,如果要实现分布均匀的左中右布局,可以使其中一个元素向左浮动,另外一个元素向右浮动,剩下的一个元素通过设置边距使其居中,从而实现左中右布局。

水平居中

  1. 内联元素水平居中
    使用 text-align: center 可以使块级元素内部的内联元素水平居中。此方法对内联元素(inline), 内联块(inline-block), 内联表(inline-table), inline-flex元素水平居中都有效。

    1
    2
    3
    .center-text {
    text-align: center;
    }

  2. 块级元素水平居中

    • 把块级元素的 margin-left 和 margin-right 设成 auto,就可以使块级元素水平居中。

      1
      margin: 0 auto;

    • 多块级元素水平居中

      1. 设置块级元素的显示类型为inline-block和父容器的text-align属性从而使多块级元素水平居中。(bug未解决)

        1
        2
        3
        4
        5
        6
        .container {
        text-align: center;
        }
        .inline-block {
        display: inline-block;
        }

      2. 利用 display: flex 属性
        justify-content:center; 主轴居中
        使用flex布局使元素居中可以不设置父元素的宽高,用子内容将其撑开。
      3. 使用绝对定位
      4. 使用绝对定位和transform

垂直居中

  1. 单行文本进行垂直居中
    父级元素高度确定,行内元素为单行文本,设置父元素的 line-height 属性与 height 相等即可。
    需要特别注意的是,line-height 的值不能设为100%,因为这里的百分比并不是相对于父元素尺寸而言,而是相对于字体尺寸来讲的。
  2. 使用绝对定位和负外边距对块级元素进行垂直居中
    此方法必须提前知道被居中元素的尺寸。
  3. 使用绝对定位和 transform
    因为 transform 中 translate 偏移的百分比就是相对于元素自身的尺寸确定的,所以此方法不需要知道被居中元素的尺寸。
  4. 使用绝对定位和 margin
    把要垂直居中的元素相对于父元素绝对定位,top和bottom设为相等的值,margin 设置为 auto 即可。如果被居中元素自身包含元素尺寸(比如图片),可以不用设置宽高。
  5. flex布局(阮一峰老师关于flex布局的blog)
    在 flex 布局中,align-items 属性定义项目在交叉轴上如何对齐。可以将其属性设置为 center:交叉轴的中点对齐,实现垂直居中,对于块级元素和行内元素都可以生效。

数据结构与算法相关

Posted on 2019-02-16

什么是算法( 算法 )

算法(algorithm),在数学(算学)和电脑科学之中,为任何良定义的具体计算步骤的一个序列,常用于计算、数据处理和自动推理。精确而言,算法是一个表示为有限长列表的有效方法。算法应包含清晰定义的指令用于计算函数。
以下是高德纳在他的著作《计算机程序设计艺术》里对算法的特征归纳:

  • 输入:一个算法必须有零个或以上输入量。
  • 输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。
  • 明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地匹配要求或期望,通常要求实际运行结果是确定的。
  • 有限性:依据图灵的定义,一个算法是能够被任何图灵完备系统模拟的一串运算,而图灵机只有有限个状态、有限个输入符号和有限个转移函数(指令)。而一些定义更规定算法必须在有限个步骤内完成任务。
  • 有效性:又称可行性。能够实现,算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。
    常见算法分类:
  • 分治法:把一个问题分区成互相独立的多个部分分别求解的思路。这种求解思路带来的好处之一是便于进行并行计算。
  • 动态规划法:当问题的整体最优解就是由局部最优解组成的时候,经常采用的一种方法。
  • 贪婪算法:常见的近似求解思路。当问题的整体最优解不是(或无法证明是)由局部最优解组成,且对解的最优性没有要求的时候,可以采用的一种方法。
  • 线性规划法
  • 简并法:把一个问题通过逻辑或数学推理,简化成与之等价或者近似的、相对简单的模型,进而求解的方法。

什么是数据结构(数据结构)

在计算机科学中,数据结构(英语:data structure)是计算机中存储、组织数据的方式。

  1. 常见的数据结构
    1. 数组(Array)
    2. 堆栈(Stack)
      • 先进后出
      • 可以用数组实现
      • 举例:盗梦空间
    3. 队列(Queue)
      • 先进先出
      • 可以用数组实现
      • 举例:排队
    4. 链表(Linked List)
      • 数组无法直接删除中间的一项,链表可以
      • 用哈希(JS里面用对象表示哈希)实现链表
      • head、node 概念
    5. 树(Tree)
      • 举例:层级结构、DOM
      • 概念:层数、深度、节点个数
      • 二叉树
      • 满二叉树
      • 完全二叉树
      • 完全二叉树和满二叉树可以用数组实现
      • 其他树可以用哈希(对象)实现
      • 操作:增删改查
      • 堆排序用到了 tree
      • 其他:B树、红黑树、AVL树
    6. 图(Graph)
    7. 堆积(Heap)
    8. 哈希表(Hash)
      • 计数排序中的桶(复杂度 O(n+max),比快排还快
      • 桶排序 与计数排序的区别
      • 基数排序 与计数排序的区别
  2. 数据结构和算法是互相依存、不可分开的
    1. 我们要解决一个跟数据相关的问题。
    2. 分析这个问题,想出对应的数据结构。
    3. 分析数据结构,想出算法。

堆排序可视化
堆排序JS代码完整讲解

CSS相关

Posted on 2019-02-15

4种引入方式

内联 style 属性
style 标签
外部 css link
@import url(./b.css);

float

浮动元素的父级元素上添加 clearfix 属性,解决浮动元素的bug

1
2
3
4
5
.clearfix::after {
content: '';
display: block;
clear: both;
}

块级元素的高度由其内部文档流元素的高度总和决定。
文档流:文档内元素的流动方向。

  • 内联元素从左往右流动,如果遇到阻碍(宽度不够),换行继续从左往右流动。
  • 块级元素,每一个块占用一行,从上往下依次流动。

伪元素

所有非空标签都有伪类,比如 <div> 标签,默认为隐藏属性,可以通过 CSS 显示出来并设置相关属性。

1
2
3
4
5
6
div::before{
conntent:'';
}
div::after{
conntent:'';
}

如果设置伪元素属性,比如 content ,所有 <div> 标签前后都会加上相关的值,并且在网页上无法选定该元素。

CSS中的块级元素、内联元素(行内元素)

  • Block element 块级元素
    以块显示的元素,高度宽度都是可以设置的。块级元素默认状态下每次都占据一整个行,后面的内容也必须再新起一行显示。当然非块级元素也可以通过 CSS 的 display:block; 将其更改成块级元素。块级元素一般是其他元素的容器元素。
    块元素(block element)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    address - 地址
    blockquote - 块引用
    center - 举中对齐块
    dir - 目录列表
    div - 常用块级容易,也是css layout的主要标签
    dl - 定义列表
    fieldset - form控制组
    form - 交互表单
    h1 - 大标题
    h2 - 副标题
    h3 - 3级标题
    h4 - 4级标题
    h5 - 5级标题
    h6 - 6级标题
    hr - 水平分隔线
    isindex - input prompt
    menu - 菜单列表
    noframes - frames可选内容(对于不支持frame的浏览器显示此区块内容)
    noscript - 可选脚本内容(对于不支持script的浏览器显示此内容)
    ol - 排序列表
    p - 段落
    pre - 格式化文本
    table - 表格
    ul - 非排序列表
  • Inline element 内联元素
    任何不是块级元素的可见元素都是内联元素,其表现的特性是“行布局”形式。内联元素的高度宽度都是不可以设置的,其宽度就是自身内容的高宽度。我们常用到的\<a>、\<span>、\<em>都属于内联元素。内联元素的显示特点就是像文本一样的显示,不会独自占据一个行。当然块级元素也能变成内联元素,那就是通过 CSS 的 display:inline; 和 float 来实现。
    内联元素(inline element)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    a - 锚点
    abbr - 缩写
    acronym - 首字
    b - 粗体(不推荐)
    bdo - bidi override
    big - 大字体
    br - 换行
    cite - 引用
    code - 计算机代码(在引用源码的时候需要)
    dfn - 定义字段
    em - 强调
    font - 字体设定(不推荐)
    i - 斜体
    img - 图片
    input - 输入框
    kbd - 定义键盘文本
    label - 表格标签
    q - 短引用
    s - 中划线(不推荐)
    samp - 定义范例计算机代码
    select - 项目选择
    small - 小字体文本
    span - 常用内联容器,定义文本内区块
    strike - 中划线
    strong - 粗体强调
    sub - 下标
    sup - 上标
    textarea - 多行文本输入框
    tt - 电传文本
    u - 下划线
    var - 定义变量
  • 可变元素
    可变元素为根据上下文语境决定该元素为块元素或者内联元素。

    1
    2
    3
    4
    5
    6
    7
    8
    applet - java applet
    button - 按钮
    del - 删除文本
    iframe - inline frame
    ins - 插入的文本
    map - 图片区块(map)
    object - object对象
    script - 客户端脚本

CSS 选择器优先级

  1. 越具体的优先级越高。
  2. 写在后面的,覆盖写在前面的。
  3. important! 优先级最高,尽量不用。

HTML标签

Posted on 2019-02-14

<iframe> 标签(可替换标签)

嵌套页面:<iframe src="https://www.baidu.com" name="xxx"></iframe>

  1. 可用 css 调整嵌套页面的宽高度。
  2. 例:可在主页面内与 <a> 标签合用,为 <iframe> 标签设置 name 属性,为 <a> 标签设置相同 value 的 target 属性,即可在当前页面内点击不同链接在嵌套页面中进行跳转。
  3. frameborder 属性为嵌套页面的边框,设置 value 值为 0 即可隐藏边框。
  4. <iframe> 的 src 属性支持相对路径。

<a> 标签

<a> 标签定义超链接,用于从一张页面链接到另一张页面,最重要的属性是 href 属性,它指示链接的目标。(一般为 GET 请求)

  1. target 属性
    • <a href="http://www.qq.com" target="_blank">QQ</a> 在新开页面打开网页。
    • <a href="http://www.qq.com" target="_self">QQ</a> 在当前页面打开网页。
    • <a href="http://www.qq.com" target="_parent">QQ</a> 在上一级页面打开网页。
    • <a href="http://www.qq.com" target="_top">QQ</a> 在最顶级页面打开网页。
  2. download 属性
    • <a herf=“http://qq.com” download>下载</a> 下载链接所指的页面。

      后端一般为:Content-type: application/octet-stream

  3. herf 属性
    • <a href="qq.com">QQ</a> 相对路径,会在当前目录下查找”qq.com”文件。
    • <a href="http://qq.com">QQ</a> 表明HTTP或HTTPS协议,一般这样写。
    • <a href="//qq.com">QQ</a> 浏览器会根据当前协议,补全无协议链接的协议。
    • <a href="#hi">QQ</a> 跳转到页面锚点。
    • <a href="?name=yang">QQ</a> 自动添加查询路径,会发起 GET 请求。
    • <a href="javascript: alert(hi);">QQ</a> 伪协议,点击会直接执行js语句。
    • <a href="javascript:;">QQ</a> 可以实现点击链接不发生任何事。
    • 应该尽量不使用 file:// 协议预览网页,以免无协议链接出错。

<form> 标签

<form>标签用于为用户输入创建 HTML 表单,表单能够包含 input 元素,比如文本字段、复选框、单选框、提交按钮等等。表单还可以包含 menus、textarea、fieldset、legend 和 label 元素。表单用于向服务器传输数据。

1
2
3
4
5
<form action="users" method="POST">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>

  1. action 属性:指定请求路径。
  2. 默认 method 为 GET,一般设置为 POST。
  3. 表单提交使用 UTF-8 编码。
  4. name 属性的值会作为 form data 部分的 key 提交。(如果 method 属性为GET,这部分内容会被浏览器添加到查询参数中。)
  5. <form> 必须要有提交按钮,否则无法提交表单。
  6. <form> 标签与 <a> 标签的 target 属性完全一致。

<input> 标签

<input> 标签规定了用户可以在其中输入数据的输入字段。在 <form> 标签中使用,用来声明允许用户输入数据的 input 控件。输入字段可通过多种方式改变,取决于 type 属性。

  1. type 属性:<input> 标签的 type 属性有很多种。
    • button:如果一个 <form> 里面只有一个 <button> 按钮,且没有设置 type 属性,则会自动升级为当前标签的 submit 按钮。这种情况下: <button>button</button> 等价于 <input type="submit" value="提交">。另外<input type="button" value="提交"> 在任何情况下无效。
    • label:可以使用 <label> 元素来定义 <input> 元素的标注。
      点击 select 时,可以同时点击到 <input> 元素。(<input> 中的 id 属性 对应 <label> 中的 for 属性)
      <input type="checkbox" id="1"><label for="1">select</label>
      可以用 <label> 将 <input> 包起来,简化上边的写法。
      <label><input type="checkbox">select</label>
    • radio&checkbox:可以在 type 后边分别设置 name 和 value 的值,提交的时候可以将选择情况一并提交到服务器。另外,当多个<input> 的 type 属性为 radio 时,后边 name 属性名字一样则为担单选,否则为多选,类似于 checkbox 属性。

<select> 标签

<select> 元素用来创建下拉列表。<select> 元素中的 <option> 标签定义了列表中的可用选项。

  1. name 属性:定义下拉列表的名称。
  2. multiple 属性:当该属性为 true 时,可选择多个选项。
  3. size 属性:规定下拉列表中可见选项的数目。
  4. required:规定用户在提交表单前必须选择一个下拉列表中的选项。
  5. disabled:当该属性为 true 时,会禁用下拉列表。
  6. autofocus:规定在页面加载时下拉列表自动获得焦点。
  7. 元素中的 <option> 可以设置 disabled 属性和 selected 属性,分别该选项不可选和默认已选择选项。

<textarea> 标签

<textarea> 标签定义一个多行的文本输入控件。可以通过 cols 和 rows 属性来规定 textarea 的尺寸大小,不过更好的办法是使用 CSS 的 height 和 width 属性,也可以用 CSS 固定尺寸大小style=resize:none;width=200px;height=100px;

<table> 标签

<table> 标签定义 HTML 表格,border 属性可以调整表格边框。比如可以用CSS使边框合并为一条线。

1
2
3
table{
border-collapse: collapse;
}

<table> 标签内含有3个主要标签:

  1. <thead> 表格头。
  2. <tbody> 表格主体。
  3. <tfoot> 表格脚。

上边3个主要标签与代码先后顺序无关,浏览器会自动调整为从头到脚的顺序,如果不写上边3个标签,则浏览器则会自动将内容补到<tbody> 里边,这3个标签可以含有以下标签:

  1. <tr> 定义HTML表格中的一行单元格,成对出现,一个 <tr> 元素包含一个或多个 <th> 或 <td> 元素。
  2. <th> 表示HTML表格的表头部分,该标签中的内容会以粗体显示并居中。
  3. <td> 定义 HTML 表格中的标准单元格,表示表格中的数据,通常是普通的左对齐文本。

<colgroup> 表示 HTML 的表格列组,可以用<col> 添加属性。

  1. span 规定列组应该横跨的列数。如<col span="3" style="background-color:blue">,表示前3列背景颜色为蓝色。如果有多个<col>,第一个 span 属性默认值为1,后边的依次以前一个<col> span 属性值递增。
  2. width 规定列组的宽度。列数根据 <col> 的 次序递增。
  3. bgcolor 规定列组的背景色。<col span="2" bgcolor=blue> 等价于 <col span="3" style="background-color:blue">

<dl> 标签

<dl> 标签定义一个描述列表。
<dl> 标签与<dt> (定义项目/名字)和<dd> (描述每一个项目/名字)一起使用。
<dl> 标签必须有开始标签和结束标签。

#

HTML 简介

Posted on 2019-02-14

W3C

万维网联盟(World Wide Web Consortium,W3C),又称W3C理事会,是万维网的主要国际标准组织。为半自治非政府组织(quasi-autonomous non-governmental organisation)。维基百科

MDN

Mozilla Developer Network(简称MDN),是一个集中所有Mozilla基金会产品和网络技术开发文件的网站。

HTML

超文本标记语言 (HyperText Markup Language)

  1. HTML 版本(W3C 组织制定规范)
    1. HTML 4.01
    2. XHTML
    3. HTML 5
    4. HTML 5.1
  2. 规范文档(Specifications)
    • W3C 根据浏览器的实际情况总结文档。
  3. DOCTYPE
    • 用来选择文档类型。<!DOCTYPE html>
  4. 常见标签
    • a、form、input、button、h1、p、ul、ol、small、strong、div、span、kbd、video、audio、svg。
    • 除了 div 和 span 标签,其他标签都有默认样式。
    • MDN 上有所有标签的文档 HTML所有元素列表。
  5. 空标签
    • 没有闭合的标签称为空标签,他们不存在成对的情况,在HTML中,在空标签上使用闭标签是无效的。
    • 常见有以下标签为空标签:
      <area>
      <base>
      <br>
      <col>
      <colgroup> 
      <command>
      <embed>
      <hr>
      <img>
      <input>
      <keygen>
      <link>
      <meta>
      <param>
      <source>
      <track>
      <wbr>
      
  6. 可替换标签
    • 指标签会被替代,例如img标签会被下载的图片替代。
    • 典型的可替换标签有:
      <img>
      <object>
      <video>
      <textarea>
      <input>
      
    • 特殊的可替换标签
      <audio>
      <canvas>
      

HTTP

Posted on 2019-02-12

URL

统一资源定位符(Uniform Resource Locator)

  • 完整的URL包括协议、域名、路径、查询字符串、锚点和端口。
  • 通过 URL 你可以确定一个「唯一的」地址(网址)。

HTTP

超文本传输协议(HTTP,HyperText Transfer Protocol)

  • HTTP 的作用就是指导浏览器和服务器如何进行沟通。
  • 使用 curl 命令发送请求:
    curl -s -v -H “key: value” -- "https://www.baidu.com"
    
  • -v显示请求详细信息
  • -X 指定请求方式
    curl -X POST -s -v -H “Frank: xxx” – “https://www.baidu.com"
  • -H增加头部信息

    HTTP请求

    请求格式:
    1 动词 路径 协议/版本
    2 Key1: value1
    2 Key2: value2
    2 Key3: value3
    2 Content-Type: application/x-www-form-urlencoded
    2 Host: www.baidu.com
    2 User-Agent: curl/7.54.0
    3 
    4 要上传的数据
    
    1. 请求行:请求方法(GET POST PUT PATCH DELETE HEAD OPTIONS)、路径(URL)、HTTP协议版本。
    2. 请求头(key: value形式):
      User-Agent:产生请求的浏览器类型。
      Accept:客户端可识别的内容类型列表。
      Host:主机地址。
      Content-Type:标注了第 4 部分的格式
    3. 第三部分永远都是一个回车(\n),用来区分第二部分与第四部分。
    4. 要上传的数据,post 方法中,数据以 key: value 形式发送。

      用 Chrome 发请求
    5. F12,点击 Network。
    6. 地址栏输入网址。
    7. 在 Network 点击,查看 request,点击「view source」。

      HTTP响应

      响应格式
      1 协议/版本号 状态码 状态解释
      2 Key1: value1
      2 Key2: value2
      2 Content-Length: 17931
      2 Content-Type: text/html
      3
      4 要下载的内容
    8. 状态行:协议/版本号 状态码 状态解释。
    9. 响应头:包含服务器类型,日期,长度,内容类型等(key: value 形式),Content-Length 表示响应正文的长度,Content-Type 表示响应正文的格式。
    10. 响应正文:服务器返回的 HTML 页面或者 json 数据。
      1xx 指示信息–表示请求已接收,继续处理
      2xx 成功–表示请求已被成功接收、理解、接受
      3xx 重定向–要完成请求必须进行更进一步的操作。
      4xx 客户端错误–请求有语法错误或请求无法实现。
      5xx 服务器端错误–服务器未能实现合法的请求。
      
      用 Chrome 查看响应
    11. 点击 Network。
    12. 输入网址。
    13. 选中第一个响应。
    14. 查看 Response Headers,点击「view source」。
    15. 查看 Response 或者 Preview,查看响应的第 4 部分
123

yang

25 posts
1 tags
© 2019 yang
Powered by Hexo
|
Theme — NexT.Muse v5.1.4