ES6语法笔记

1.多行字符串 用反引号 `` 表示: `abc`相当于 'abc'

2.字符串连接时使用变量   使用${变量名}直接引用字符串变量

var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);

3.字符串方法:不会改变原有字符串的内容,而是返回一个新字符串

toUpperCase() 把一个字符串全部变为大写

toLowerCase() 把一个字符串全部变为小写

indexOf() 会搜索指定字符串出现的位置:没有找到的话返回-1

substring(startIndex,endIndex) 返回指定索引区间的子串,包含start不包含end;不写end的话默认到结束

subStr(startIndex,length) 返回指定索引后length个数的子串:不写length的话默认到结束

slice(start,end)     返回字符串中提取的子字符串

split()   字符串分割为数组

match()   返回匹配关键字的数组

localeCompar(str) 比较两个字符串,如果片 字符串在字母表中应该排在参数之前返回-1,相等返回0,之后返回1   'red'. localeCompar('red')  //0

4.数组方法

请注意

直接给数组赋length会改变原数组大小

如果通过索引赋值时,索引超过了范围,同意会改变原数组大小,所以访问索引时要确保索引不会越界。

indexOf() 搜索一个指定的元素的位置:

slice(start,end) 截取数组的部分元素返回一个新的数组:不写数量的话默认到结束,写end的话不包括最后一项,不改变原数组   注意:可通过slice()来复制数组

push() 数组的末尾添加若干元素

unshift() 数组的开头添加若干元素

pop() 数组的最后一个元素删除掉

shift() 数组的第一个元素删掉

sort() 可以对当前数组进行排序

对纯数组进行排序
arr.sort((a,b)=>{
    return a-b //将arr升序排列,如果是倒序return -(a-b)
})


对数组对象进行排序
arr.sort((a,b)=>{
        let value1 = a[property];
        let value2 = b[property];
        return value1 - value2;//sort方法接收一个函数作为参数,这里嵌套一层函数用
        //来接收对象属性名,其他部分代码与正常使用sort方法相同
})

reverse() 反转整个数组的元素

splice(start,数量,添加的字符串可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素,改变原数组

  1.  删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。 例如,splice(0,2)会删除数组中的前两项。
  2.  插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数) 和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如, splice(2,0,"red","green")会从当前数组的位置 2 开始插入字符串"red""green"。
  3.  替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如, splice (2,1,"red","green")会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串 "red"和"green"

concat() 方法把两个数组连接起来,并返回一个新的Array,不改变原数组

join(',') 把数组元素按照逗号拼接为字符串,返回连接后的字符串:可以不加参数直接拼接

some()  数组有一项满足条件就返回true

every()  数组每一项满足条件就返回true

5.对象

访问对象属性属于  对象名.属性名 或  对象名[属性名]    

delete 对象名.属性名    删除对象属性

对象名.hasOwnProperty(‘属性名’ )    检查对象是否含有此属性

6.Map和Set

Map是一组键值对的结构,具有极快的查找速度。

初始化Map需要一个二维数组,或者直接初始化一个空Map

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
var m = new Map()

Map具有以下方法:

m.set('Adam', 67);    //添加新的key-value
m.has('Adam');        //检查是否存在key
m.get('Adam');        //获取对应key的值
m.delete('Adam');     //删除key

Set是一组key的集合,但不存储value,key不重复。

初始化Set需要一个一维数组,或者直接初始化一个空Set

var s = new Set([1,2,3]);
var s = new Set()

Set具有以下方法:

s.add(4);        //增加key
s.delete(3);     //删除key

7.iterable

遍历Array可以采用下标循环,遍历MapSet就无法使用下标。

为了统一集合类型,ES6标准引入了新的iterable类型,ArrayMapSet都属于iterable类型。

iterable类型的集合可以通过新的  for ... of 循环来遍历

var a = ['A', 'B', 'C'];
var a = new Map();
var a = new Set();

for (var x of a) {
    console.log(x); 
}

for of的底层实现 Symbol.iterator

const qq = [1, 2, 3]
const each = (value: any) => {
  let It: any = value[Symbol.iterator]()
  let next: any = { done: false }
  while (!next.done) {
    next = It.next()
    if (!next.done) {
      console.log(next.value)
    }
  }
}
each(qq)

最佳的遍历方式通过forEach()方法

    数组:

var a = ['A','B','C'];
a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    console.log(element + ', index = ' + index);
});

    Map:类似

var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
    console.log(element);
});

    Set:类似

var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
    console.log(value);
});

8.函数

  • 普通函数定义: 

function abs(x) {
    if(x<0){
        return -x;
    }else{
        return x;
    }   
}
  • 匿名函数定义:/用法和普通函数一样,注意最后要加   ;   表示赋值结束

var abs = function (x) {
     return x;
};       

参数

1.arguments参数

函数内部有免费赠送的关键字arguments,利用arguments,你可以获得调用者传入的所有参数。

arguments类似Array,实际上arguments最常用于判断传入参数的个数。你可能会看到这样的写法:

// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
    if (arguments.length === 2) {
        // 实际拿到的参数是a和b,c为undefined
        c = b; // 把b赋给c
        b = null; // b变为默认值
    }
}

2.rest参数

函数调用时,为了获得额外的参数,通过rest返回额外参数Array

rest参数只能写在最后,前面用...标识

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);   
}

foo(1,2,3,4,5)   //rest:[3,4,5]

9.变量作用域

如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量:

如果两个不同的函数申明同一个变量,不同函数内部的同名变量互相独立,互不影响:

变量提升

JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

注意:JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。

'use strict';

function foo() {                          function foo() {                                                      
    var x = 'Hello, ' + y;                    var y;
    console.log(x);            相当于          var x = 'Hello, ' + y; 
    var y = 'Bob';                             y = 'Bob';  
}                                              console.log(x); 
                                          }
   
foo();   //返回 Hello,undefined

10.全局作用域

  1. 不在任何函数内定义的变量就具有全局作用域。
  2. 实际上,JavaScript默认有一个全局对象 window,全局作用域的变量实际上被绑定到window的一个属性:
  3. 由于函数定义有两种方式,以变量方式var foo = function () {}定义的函数实际上也是一个全局变量,因此顶层函数也会绑定到window对象:可以通过window.foo()调用

11.名字空间

全局变量会绑定到window上,不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。

减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。

// 唯一的全局变量MYAPP:
var MYAPP = {};

// 其他变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;

// 其他函数:
MYAPP.foo = function () {
    return 'foo';
};

12.块级作用域

用 let关键字替代var可以申明一个块级作用域的变量:

function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    // SyntaxError:
    i += 1;
}

13.常量

const关键字来定义常量,也拥有块级作用域

const PI = 3.14;
PI = 3; // 某些浏览器不报错,但是无效果!

14.解构赋值

同时对多个变量赋值:

var [x, y, z] = ['hello', 'JavaScript', 'ES6'];

解构赋值还可以忽略某些元素:

let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
z; // 'ES6'

如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};
var {name, age, passport} = person;
// name = 小明, age = 20, passport = G-12345678

15.解析赋值使用场景

解构赋值在很多时候可以大大简化代码。例如,交换两个变量xy的值,可以这么写,不再需要临时变量:

var x=1, y=2;
[x, y] = [y, x]

快速获取当前页面的域名和路径:

var {hostname:domain, pathname:path} = location;

如果一个函数接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中。例如,下面的函数可以快速创建一个Date对象:

function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}

它的方便之处在于传入的对象只需要yearmonthday这三个属性:

buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)

也可以传入hourminutesecond属性:

buildDate({ year: 2017, month: 1, day: 1, hour: 20, minute: 15 });
// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)

16.方法

绑定到对象上的函数称为方法

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN

var fn = xiaoming.age();  //正确

这是不行的!要保证this指向正确,必须用obj.xxx()的形式调用!

注意:在函数内部定义的函数,this指向window!

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var that = this; // 在方法内部一开始就捕获this
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - that.birth; // 用that而不是this
        }
        return getAgeFromBirth();
    }
};

xiaoming.age(); // 25

解决办法:用一个that变量首先捕获this

17.apply参数

指定函数的this指向哪个对象,可以用函数本身的apply方法

它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

function getAge() {
    var y = new Date().getFullYear();
    return y - this.birth;
}

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: getAge
};

getAge.apply(xiaoming, []);    //不用apply的话,this就会指向window报错

另一个与apply()类似的方法是call(),唯一区别是:

  • apply()把参数打包成Array再传入;

  • call()把参数按顺序传入。

对普通函数调用,我们通常把this绑定为null

装饰器

利用apply(),我们还可以动态改变函数的行为。

var count = 0;
var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数
};

parseInt('10');
parseInt('20');
parseInt('30');
console.log('count = ' + count);  // 3

18.高阶函数

一个函数接收另一个函数作为参数,这种函数就称之为高阶函数。

map / reduce

map( f(x) ) 方法 :把f(x)作用在Array的每一个元素并把结果生成一个新的Array”

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var arr2 = arr.map(String); 
console.log(arr2);        // ['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduce( f(x,y) ) 方法把一个函数作用在这个Array[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

reduce实现一个数组的求和

var arr = [1, 3, 5, 7, 9];
var arr2 = arr.reduce(function (x, y) {
    return x + y;
}); 
console.log(arr2);   // 25

filter方法

filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。

filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

例如,在一个数组中,删掉偶数,只保留奇数,可以这么写:

var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
    return x % 2 !== 0;
});
console.log(r);    // [1, 5, 9, 15]

filter()有多个参数。通常我们仅使用第一个参数,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身:

var r = arr.filter(function (element, index, self) {
            
});

利用filter,可以巧妙地去除Array的重复元素:

var arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange'];

var r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index;
});

sort方法

通常规定,对于两个元素xy,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1

sort()方法也是一个高阶函数,可以接收一个比较函数来实现自定义的排序。

var arr = [1,3,20,10,4]
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
});
console.log(arr); // [1, 3, 4, 10, 20]

注意:sort()方法会直接对Array进行修改,它返回的结果仍是当前Array

Array

every()方法可以判断数组的所有元素是否满足测试条件。

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.every(function (s) {
    return s.length > 0;
}));         // true, 因为每个元素都满足s.length>0

find()方法用于查找符合条件的第一个元素,如果找到了,返回这个元素,否则,返回undefined

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.find(function (s) {
    return s.toUpperCase() === s;
}));            // undefined, 因为没有全部是大写的元素

findIndex()查找符合条件的第一个元素,如果找到了,返回这个元素的索引,如果没有找到,返回-1

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.findIndex(function (s) {
    return s.toUpperCase() === s;
}));     // -1,没有全是大写的字符串

forEach()常用于遍历数组,不会返回新的数组,因此传入的函数不需要返回值:

var arr = ['Apple', 'pear', 'orange'];
var arr2 = [];
arr.forEach(x=>{
    arr2.push()
}); // 依次打印每个元素

19.闭包

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

1、变量作用域

要理解闭包,首先要理解javascript的特殊的变量作用域。
变量的作用域无非就两种:全局变量和局部变量。
javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量
注意点:在函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明的是一个全局变量!

2、如何从外部读取函数内部的局部变量?

出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。
那就是在函数内部,再定义一个函数。

    function f1(){
    var n=999;
    function f2(){
      alert(n); // 999
    }
  }

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。

这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

3、闭包的概念

上面代码中的f2函数,就是闭包。
各种专业文献的闭包定义都非常抽象,我的理解是: 闭包就是能够读取其他函数内部变量的函数
由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“
所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁

4、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

5、使用闭包的注意点

(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

20.generator

generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。

generator和函数不同的是,generator由  function* 定义(注意多出的*号),并且,除了return语句,还可以用yield 返回多次

function* foo(x) {
    yield x + 1;
    yield x + 2;
    return x + 3;
}

foo(5);    //直接调用foo(5)仅仅是创建了一个generator对象,还没有去执行它。

调用generator对象有两个方法

一是不断地调用generator对象的next()方法

var f = foo(5);
f.next();   // {value: 0, done: false}
f.next();   // {value: 1, done: false}
f.next();   // {value: 1, done: false}
f.next();   // {value: undefined, done: true}

每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。

返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。

当执行到donetrue时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。

二是用 for ... of 循环迭代generator对象,这种方式不需要我们自己判断done

for (var x of foo(10)) {
    console.log(x);   
}

21.创建对象

JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。

当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined

构造函数

除了直接用{ ... }创建一个对象外,JavaScript还可以用一种构造函数的方法来创建对象。它的用法是,先定义一个构造函数:

function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
}

可以用关键字new来调用这个函数,并返回一个对象:

如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this,也就是说,不需要在最后写return this;

new Student()创建的对象还从原型上获得了一个constructor属性,它指向函数Student本身

按照约定,构造函数首字母应当大写,而普通函数首字母应当小写

如果我们通过new Student()创建了很多对象,这些对象的hello函数只需要共享同一个函数就可以,这样可以节省很多内存。

只要把hello函数移动到xiaomingxiaohong这些对象共同的原型上就可以了,也就是Student.prototype

function Student(name) {
    this.name = name;
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

最后,我们还可以编写一个createStudent()函数,在内部封装所有的new操作。一个常用的编程模式像这样:

function Student(props) {
    this.name = props.name || '匿名'; // 默认值为'匿名'
    this.grade = props.grade || 1; // 默认值为1
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

function createStudent(props) {
    return new Student(props || {})
}

原型继承

JavaScript的原型继承实现方式就是:

  1. 定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this

  2. 借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;

  3. 继续在新的构造函数的原型上定义新方法。

22.浏览器对象

window:不但充当全局作用域,而且表示浏览器窗口。

window.innerWidth      浏览器内部宽

window.innerHeight     浏览器内部高

window.outerWidth      浏览器窗口的整个宽

window.outerHeight     浏览器窗口的整个高

navigator表示浏览器的信息,最常用的属性包括:

  • navigator.appName:   浏览器名称;
  • navigator.appVersion: 浏览器版本;
  • navigator.language:    浏览器设置的语言;
  • navigator.platform:      操作系统类型;
  • navigator.userAgent:   浏览器设定的User-Agent字符串。

针对不同浏览器编写不同的代码     

var width = window.innerWidth || document.body.clientWidth;

screen:表示屏幕的信息,常用的属性有

  • screen.width:  屏幕宽度,以像素为单位;
  • screen.height: 屏幕高度,以像素为单位;
  • screen.colorDepth: 返回颜色位数,如8、16、24。

location:表示当前页面的URL信息。

  • location.href             当前页面完整url
  • location.protocol;     // 'http'
  • location.host;           // 'www.example.com'
  • location.port;            // '8080'
  • location.pathname;  // '/path/index.html'
  • location.search;       // '?a=1&b=2'
  • location.hash;          // 'TOP'

location.assign()      加载新页面

location.reload()      重新加载当前页面

document:表示当前页面

要查找DOM树的某个节点,需要从document对象开始查找。最常用的查找是根据ID和Tag Name。

getElementById()getElementsByTagName()可以按ID获得一个DOM节点和按Tag名称获得一组DOM节点:

Cookie是由服务器发送的key-value标示符。因为HTTP协议是无状态的,但是服务器要区分到底是哪个用户发过来的请求,就可以用Cookie来区分。当一个用户成功登录后,服务器发送一个Cookie给浏览器,例如user=ABC123XYZ(加密的字符串)...,此后,浏览器访问该网站时,会在请求头附上这个Cookie,服务器根据Cookie即可区分出用户。

document.cookie 读取到当前页面的Cookie

由于JavaScript能读取到页面的Cookie,而用户的登录信息通常也存在Cookie中,这就造成了巨大的安全隐患,这是因为在HTML页面中引入第三方的JavaScript代码是允许的:

为了解决这个问题,服务器在设置Cookie时可以使用httpOnly,设定了httpOnly的Cookie将不能被JavaScript读取

23.双等号转换规则

24.垂直和水平居中

水平居中

  • 行内元素: text-align: center
  • 块级元素: margin: 0 auto
  • position:absolute +left:50%+ transform:translateX(-50%)
  • display:flex + justify-content: center

垂直居中

  • 设置line-height 等于height
  • position:absolute +top:50%+ transform:translateY(-50%)
  • display:flex + align-items: center
  • display:table+display:table-cell + vertical-align: middle;

25.jquery属性的相关js实现方法

jquery属性的相关js实现方法

26.Grid网格布局

https://www.cnblogs.com/cythia/p/10894598.html

27.正则表达式

你是如何学会正则表达式的? - 知乎

28.对象深拷贝

function deepClone(obj) {
    let res = obj instanceof Array ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            res[key] = typeof obj[key] == "object" ? 
                deepClone(obj[key]) : obj[key];
        }
    }
    return res;
}

29.数组迭代方法

every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true

filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。

forEach():对数组中的每一项运行给定函数。这个方法没有返回值。

map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true

以上方法都不会修改数组中的包含的值,每个方法使用的函数包含三个参数,item,index,array,例如:

var arr = [1,2,3,4,5];
var result = arr.every(function(item,index,array){
    return item > 0;
}) 
alert(result); // true

30.数组归并方法

  • reduce() 从前向后迭代每一项,返回一个最终值
  • reduceRight() 从后向前迭代每一项,返回一个最终值

每个方法接收的函数都有4个参数,前一个值prev、当前值cur、当前值索引index、数组对象array,例如:

使用 reduce()方法可以执行求数组中所有值之和的操作,比如:
var values = [1,2,3,4,5]; 
var sum = values.reduce(function(prev, cur, index, array){ 
 return prev + cur; 
}); 
alert(sum); //15

31.在浏览器地址栏键入URL,按下回车之后会经历以下流程

  1. URL解析:浏览器对URL进行解析,获取协议、主机名、端口号、路径、查询参数、锚点等信息。

  2. DNS解析:浏览器需要将主机名解析成对应IP地址,浏览器会检查缓存中是否存在对应IP,如果没有则通过DNS解析得到对应IP。

  3. TCP连接:浏览器使用TCP协议与Web服务器建立连接(三次握手)。

  4. 发送HTTP请求:浏览器向服务器发送HTTP请求,请求可以包含请求头、请求体等信息。

  5. 服务器响应:服务器接收到请求后,根据路径和参数等信息返回相应的响应头和响应体,并向浏览器发送HTTP响应,响应中包含状态码、响应头、响应体等信息。

  6. 接收响应:浏览器接收服务器返回的HTTP响应,然后开始渲染页面。

  7. 浏览器解析HTML: 接收到HTTP响应后,浏览器开始解析HTML文档。HTML文件中包含各种标记或标签,浏览器根据标记或标签的含义对页面进行格式化和呈现。

  8. 浏览器发送其他请求: HTML文档中包含许多其他文件,例如js脚本、CSS样式表、图片、视频等。当浏览器遇到引用这些文件的标记时,会向服务器发送进一步的请求来获取这些文件。

  9. 完成渲染: 浏览器解析完所有相关文件后,将页面元素组合在一起,然后呈现给用户。

  10. 断开连接:数据传输完成后,浏览器和服务器断开连接(四次挥手)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值