前端笔试题目整理

JS

变量提升

fn()      // 由于函数表达式是不能进行变量提升,所以这里执行的 打印2的
var fn = function () {
    console.log(1)
}
function fn() {
    console.log(2)
}
fn() //1
var func1 = {
    name: 'a',
    test: function () {
        console.log(this.name);
    }
}
name = 'global'
func1.test()   //a
func = func1.test     //相当于 func = function(){.....}  这里的this指向 window
func() // global

function func2(){
    var name = 'func2'
    func()
}
func2()   //global
let obj = {
    sangfor : 100,
    log() {
        sangfor = 200;   //在这里,没有使用 var或者let来定义变量,这就是一个陷阱。没有使用这两个的话,js就会默认是使用var在外部定义的,然后再内部更改值。所以这个变量变成了全局变量
        console.log(this.sangfor);
    }
}
obj.log()      // 100
let { log } = obj
log() //这个函数this就是指向全局   200
let x = 10;
let foo = () => {
  // 这里访问 x 就会在当前作用域内找 x
  // 如果没有下面的 let x = 20
  // 当前作用域就找不到,然后就会继续找外层变量,最后输出 10
  // 但是下面有声明,声明会提升到当前代码块最前面
  // 这个时候 x 还没有初始化,存在暂存死区中,访问就会抛出 ReferenceError
  console.log(x);
  let x = 20;
  x++;
};
foo();
//如果把里面的 let 换成 var 就不会报错,显示 undefined
//就是因为 let 是在编译时才会初始化,var 在声明时就会初始化
var name = 'World!';
(function () {
    if (typeof name === 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

//变量提升,相当于

var name = 'World!';
(function () {
    var name;
    if (typeof name === 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
//Goodbye Jack

	var a,b;

	(function(){

	    alert(a);   //这是第一个输出的,先在局部没找到a变量,然后去全局找,找到了但没定义,输出undefined

	    alert(b);    //这是第二个输出的,其他同上

	    var a=b=3;    //拆解成var a=b; b=3; 然后,b=5前面没有var,相当于声明为全局变量

	    alert(a);     //这是第三个输出,局部变量a=3

	    alert(b);     //这是第四个输出,全局变量b=3

	})();            //这个函数体已经执行完毕,里面的内存已经被垃圾回收器回收,局部变量a销毁

	alert(a);        //这是第五个输出,全局变量a=undefined

	alert(b);        //这是第六个输出,全局变量b=3

	

	故正确答案是undefined,undefined,3,3,undefined,3;

let a = { n: 1 }; 
let b = a; //a和b指向同一个对象
a.x = a = { n: 2 }; 
// 由于.的优先级比 = 高,所以先执行 a.x,于是现在的a和b都是 { n: 1,x:undefined }
// 然后执行 a = {n:2},于是a指向了 {n:2},已经不再是之前的a
// 最后执行 a.x = a, 所以b和之前的a指向 {n:1,x:{n:2}}
console.log(a); //{n:2}
console.log(b); //{n:1,x:{n:2}}
var a = 10;
function a(){}
console.log(typeof a) //number

//由于函数声明的优先级比var要高,所以等价于

function a(){}
var a;
a = 10
console.log(typeof a) //所以打印的结果是 number
var x=10;
function cals(myNum) {
            return x+myNum;
        }
cals(7) //17

//等价于

function cals(myNum) {
            return x+myNum;
        }
var x;
x=10
cals(7) 
var foo=”Hello”;
(function(){
    var bar=”World”;
    alert(foo+bar); // hello world
})();
alert(foo+bar); //报错

//(function(){})()这是一个匿名自执行函数,在函数内部声明的变量bar为局部变量,函数外部无法调用,所以第二次打印报错;第一次打印时。函数通过作用域链可以访问到外部的全局变量foo;因此第一次打印为hello world
(function() {
    var x=foo();
    var foo=function foo() {
        return "foobar"
    };
    return x;
})();
//类型错误
//变量提升
//等价于
var foo;
var x = foo();
foo = function foo() {...}
//当执行到 x = foo() 时,由于foo未被定义为函数
function checkAge(age) {
if (age < 18) {
const message = "Sorry, you're too young."
} else {
const message = "Yay! You're old enough!"
}
return message
}
console.log(checkAge(21)) //ReferenceError
//const 和 let 声明的变量是具有块级作用域的,块是大括号( {} )之间的任何东西, 即上述情况 if / else 语句的花括号。 由于块级作用域,我们无法在声明的块之外引用变量,因此抛出 ReferenceError

基本数据类型的转换

1、转换成Boolean

  1. 空字符 => false ,非空字符串=> true
  2. 0 、 NaN => false ,除了 0 和 NaN 以外=> true 
  3. object 为 null 时,会转换为 false ,如果 object 不为 null ,则都会转换成 true

这里的object为null的意思是说,object = null这种形式

而 object = [] or object = {}都不是 null的意思

  1. 任何 Function 类型都会转换为 true
  2. Null => false 
  3. Undefined => false 

2、转换成Number

  1. 如果值为 null ,则返回0
  2. 如果值为 undefined ,则返回 NaN
  3. 字符串不包含任何字符,或为连续多个空格,则会转换为0
  4. 如果是对象类型,则会调用对象的 valueOf( ) 函数获取返回值,并且判断返回值能否转换为 Number 类 型,如果不能,会调用对象的 toString( ) 函数获取返回值,并且判断是否能够转换为 Number 类型。如果也不 满足,则返回 NaN

运算符

  1. 如果比较的值是字符串类型,则判断每个字符是否相等,如果全部相等,返回 true ,否则返回`false`
  2. 如果比较的值都是引用类型,则比较的是引用类型的地址,当两个引用指向同一个地址时,则返回 true ,否则 返回`false`
  3. null == undefined比较结果是true,除此之外,null、undefined和其他任何结果的比较值都为false
  4. NaN和其他任何类型比较永远返回false(包括和他自己)
  5. 如果比较的是字符串和数值类型数据,则会将字符串转换为数值后再进行比较,如果转换后的数值是相等的 则返回 true ,否则返回 false
  6. 如果比较的时候,有一方的类型是 boolean 类型,会将 boolean 类型进行转换, true 转换为1, false 转 换0,然后再进行比较
console.log(([]) ? true : false);// => 数组是对象,这里不是等于null,所以是true
console.log(([] == false ? true : false));// => console.log(0==0?true:false);
console.log(({} == false) ? true : false);// => console.log((NaN==0)?true:false);

console.log('11' > '2');  // 字符串对比  是一个字符对应对比的  1>2 ==>false 
console.log('0' == true); // 布尔值与其他值比较时,转化成数字类型===> 1  然后字符串跟数字类型比较  字符串转成数字类型
console.log([] == []);
console.log([] == false); //布尔值和其他相比较的话,会转化成Number类型  []转换为 0
console.log(NaN == false); //NaN和其他任何类型比较永远返回false(包括和他自己)。

// null == undefined比较结果是true,除此之外,null、undefined和其他任何结果的比较值都为false。
console.log(undefined == '0');
console.log(null == 0);
console.log(null == undefined);

typeof运算符

类型结果
Number、NaNnumber
Stringstring
Object、null、Arrayobject
Functionfunction
Undefinedundefined
Booleanboolean
Symbolsymbol
function Sangfor(name) {
    return this.name = name

}

console.log([0, '0', [], {}, null].map(i => typeof new Sangfor(i).name)) //[ 'number', 'string', 'undefined', 'undefined', 'object' ]

console.log(new Sangfor([]).name);  //new Sangfor([]) 返回了 []  [].name 肯定是undefinded
console.log(new Sangfor(null).name); // null

console.log(typeof []); //object
console.log(typeof {}); //object
console.log(typeof null); //object
const name = "Lydia Hallie";
console.log(!typeof name === "object"); //false
console.log(!typeof name === "string"); //false
typeof name 返回 "string" 。字符串 "string" 是一个 truthy 的值,因此 !typeof name 返回一个布尔值false。false === "object" 和 false === "string" 都返回 false 。
(如果我们想检测一个值的类型,我们应该用 !== 而不是 !typeof )

对象中的get和set是当对象赋值和取值自动调用的

let oo = {
    get sangfor() {
        console.log('get')
    },
    set sangfor(v) {
        console.log('set')
    },
}
oo.sangfor = '100'
console.log(oo.sangfor) //set get  undefined

toString():对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用

valueOf():如果对象没有原始值,valueOf() 就会返回对象自身

let x = {
    toString(){
        return 20
    },
    valueOf(){
        return 30
    }
}
console.log(x == '20'); //因为这里没有原始值,所以在这里调用的是 valueOf 而不是 toString
console.log(x == 30);

for...in... 和 for...of...的区别

  1. for...in...:返回的值是键值对中的键
  2. for...of...:返回的值是键值对中的值,但是要有iterator接口
const obj = {
        a: 1,
        b: 2,
        c: 3
    }
    for (let i in obj) {
        console.log(i)
        // a
        // b
        // c
    }
    for (let i of obj) {
        console.log(i)
        // Uncaught TypeError: obj is not iterable 报错了
  }

Object.defineProperty 该方法会直接在一个对象上定义 一个 新属性,或者修改一个对象的现有属性

let xx = {
    sangfor: '100'
};
Object.defineProperty(xx, 'sangfor', {
    get() {
        return '200'
    }
})
xx.sangfor = '300'
console.log(xx.sangfor); //200
const person = { name: "Lydia" };
Object.defineProperty(person, "age", { value: 21 });
console.log(person); //{ name: "Lydia", age: 21 }
console.log(Object.keys(person));//{ name: "Lydia", age: 21 }
//defineProperty 方法给对象添加了一个属性之后,属性默认为 不可枚举

原型链

let Base = {
    name: 'base'
}
let A = function () {
    this.name = 'a'
}
A.prototype = Object.create(Base)
let a = new A();
Base.name = 'new_name';
console.log(a.name);  //a
delete a.name;
console.log(a.name); //new_name
function A(x) {
 this.x = x;
}
A.prototype.x = 1;

function B(x) {
 this.x = x;
}
B.prototype = new A();

const b = new B(3);
delete b.x;
console.log(b.x); //undefined
//b=new B(3)设置的是B方法中的this.x=3 (B),delete b.x也是删除的B上的x,此时b.x就寻找A中的x,首先是构造函数中的this.x (A),没有给这个x赋值,所以返回undefined。
function f1(){}

console.log(f1.prototype,typeof f1.prototype); //{} object
console.log(Object.prototype,typeof Object.prototype);//[Object: null prototype] {} object
console.log(Function.prototype.__proto__) // [Object: null prototype] {}
console.log(Function.prototype) // {}
console.log(Function.prototype.prototype,typeof Function.prototype.prototype);//undefined undefined
console.log(f1.prototype.constructor,typeof f1.prototype.constructor);//[Function: f1] function
var F=function(){};
Object.prototype.a=function(){};
Function.prototype .b=function(){};
var f=new F();
// f 只能取到a  取不到b
// 用new操作符创建的f只是对象,所以只能继承于Object.prototype 

Chrome中,1rem =10px

new String( ) 方式生成的字符串是字符串对象

function showCase(value) {
    switch (value) {
        case 'A':
            console.log('case A');
            break;
        case 'B':
            console.log('case B');
            break;
        case undefined:
            console.log('case undefined');
            break;
        default:
            console.log('Do not Know');
            break;
    }

}
console.log(new String('A'));  //    [String:'A']
showCase(new String('A')) //'Do not Know'

JS内置对象

  1. Array对象
  2. Date对象
  3. 正则表达式对象
  4. string对象
  5. Global对象
  6. JSON等

JS内置迭代对象

  1. String
  2. Array
  3. TypedArray
  4. Map
  5. Set

JS全局函数

  1. escape( )
  2. eval_r( )
  3. isFinite( )
  4. isNaN( )
  5. parseFloat( )
  6. parseInt( )
  7. unescape( )

改变作用域链

  1. with
  2. try-catch
  3. eval

javascript异步模式

  1. 回调函数
  2. 事件监听
  3. 发布/订阅
  4. Promises

RegExp对象方法

  1. test()
  2. exec()
  3. compile()

 Generator函数

function* generatorOne() {
yield ['a', 'b', 'c'];
}
function* generatorTwo() {
yield* ['a', 'b', 'c'];
}
const one = generatorOne()
const two = generatorTwo()
console.log(one.next().value) // ['a', 'b', 'c']
console.log(two.next().value) // a

通过 yield 关键字, 我们在 Generator 函数里执行 yield 表达式. 通过 yield* 关键字, 我们可以在一个 Generator 函数里面执行( yield 表达式)另一个 Generator 函数, 或可遍历的对象 (如数组). 在函数 generatorOne 中, 我们通过 yield 关键字 yield 了一个完整的数组 ['a', 'b', 'c'] 。函数 one 通 过 next 方法返回的对象的 value 属性的值 ( one.next().value ) 等价于数组 ['a', 'b', 'c']

在函数 generatorTwo 中, 我们使用 yield* 关键字。就相当于函数 two 第一个 yield 的值, 等价于在迭代器中 第一个 yield 的值。数组 ['a', 'b', 'c'] 就是这个迭代器. 第一个 yield 的值就是 a , 所以我们第一次调 用 two.next().value 时, 就返回 a 。

回流和重绘

reflow:当render树的一部分或者全部因为大小边距等问题发生改变而需要重建的过程,叫做回流

repaint:当诸如颜色背景等不会引起页面布局变化,而只需要重新渲染的过程叫做重绘

回流一定伴随着重绘,而重绘却可以单独出现

  1. display:none指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint。
  2. visibility:hidden指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint

手写AJAX

// 第一步需要new一个XMLHttpRequest对象
const xhr = new XMLHttpRequest()
// 第二步使用传入请求方式,请求路径,同步还是异步
// 最后的一个参数,true是代表异步请求,false是代表同步请求,默认是异步
xhr.open('GET', '/api', true)
// 当状态改变的时候发送请求
xhr.onreadystatechange = function() {
    // xhr.readyState的几种状态
    // 0 - (未初始化)还没有调用send()方法
    // 1 - (载入)已调用send()方法,正在发送请求
    // 2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
    // 3 - (交互)正在解析响应内容
    // 4 - (完成)响应内容解析完成,可以在客户端调用
    if(xhr.readyState === 4){
        // http请求状态码 200代表成功
        if(xhr.status === 200){
            alert(xhr.responseText)
        }
    }
}
xhr.send(null)

执行顺序

  1. 宏任务先执行,setTimeout,他是第二个宏任务,将它扔进宏任务事件队列里先排队
  2. promise的回调,他是一个微任务,将它扔进微任务事件对列中,  注意:当.then()里没写回调时,当宏任务看
  3. 第一个宏任务(主程序)执行完,执行全部的微任务,再执行下一个宏任务(settimeout)
  4.  await 之后的代码在 promise 被完成后以 .then 执行
Promise.resolve().then(()=>{
    console.log('Promise1')    //有回调,微任务                   1
})
setTimeout(function(){        //宏任务,放进队列           2
    console.log('setTimeout1')
},10)
setTimeout(()=>{            //宏任务,放进队列
    console.log('setTimeout2');     //                 3
    Promise.resolve().then(()=>{
        console.log('Promise2')    //                   4
    })
},10)
// Promise1 setTimeout1 setTimeout2  Promise2
console.log(1);                                //宏任务         1
setTimeout(function () {                       //宏任务,放进队列
    console.log(2);                            //              6
})
new Promise(function (resolve, reject) {      
    console.log(3);                           //宏任务          2
}).then(console.log(4));                      //无回调,宏任务          3
console.log(10);                              //宏任务          4
new Promise(function (resolve, reject) {
    setTimeout(function () {                 //宏任务,放进队列
        console.log(5);                     //                 7
    });
}).then(console.log(6));                    //无回调,宏任务            5
setTimeout(function () {                   //宏任务,放进队列
    new Promise(function (resolve, reject) {
        console.log(7);                    //                   8
    });
})
//  1 3 4 10 6 2 5 7
setTimeout(function () { console.log(1) }, 0);     //宏任务,放进队列     5
new Promise(function (resolve) {
    console.log(2)                                // 宏任务      1
    for (var i = 0; i < 10000; i++) {
        i == 9999 && resolve()
    }
    console.log(3)                               // 宏任务      2
}).then(function () {
    console.log(4)                              //有回调,微任务 4
});
console.log(5);                                //   宏任务     3
// 2 3 5 4 1
async function async1() {
    console.log('1')                 // 2
    await async2();
    console.log('2')     // 抽出 await 之后的代码放到.then回调   微任务     6
}
async function async2() {
    console.log('3')               // 3
}
console.log('4')                  //  1

setTimeout(function(){
    console.log('5')          // 8
},0)

async1()
new Promise(function (resolve){
    console.log('6')            // 4
    resolve()
}).then(function(){
    console.log('7')              // 7
})
console.log('8')            // 5

// 4 1 3 6 8 2 7 5

函数传递参数都是按值传递

function test(a){
a=a+10;
}
var a=10;
test(a);
console.log(a); // 10
//函数参数仅仅是被传入变量复制给了的一个局部变量,改变这个局部变量不会对外部变量产生影响。
let obj = {};
function changeValue(obj){
  obj.name = 'ConardLi';
  obj = {name:'code秘密花园'};
}
changeValue(obj);
console.log(obj.name); // ConardLi

函数参数传递的并不是变量的引用,而是变量拷贝的副本,当变量是原始类型时,这个副本就是值本身,当变量是引用类型时,这个副本是指向堆内存的地址 

function getInfo(member, year) {
member.name = "Lydia";
year = "1998";
}
const person = { name: "Sarah" };
const birthYear = "1997";
getInfo(person, birthYear);
console.log(person, birthYear); //{ name: "Lydia" }, "1997"

函数默认传参情况

const value = { number: 10 };
const multiply = (x = { ...value }) => {
console.log(x.number *= 2);
};
multiply(); //20
multiply(); //40
multiply(value);//20
multiply(value);//20

 在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 "undefined" ,那么参数的 值将是默认值。上述例子中,我们将 value 对象进行了解构并传到一个新对象中,因此 x 的默认值为 {number:10} 。

默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 multiply 函数且 不传递值,那么每一次 x 的默认值都为 {number:10} ,因此打印出该数字的乘积值为 20 。

第三次调用 multiply 时,我们传递了一个参数,即对象 value 。 *= 运算符实际上是 x.number = x.number * 2 的简写,我们修改了 x.number 的值,并打印出值 20 。

第四次,我们再次传递 value 对象。 x.number 之前被修改为 20 ,所以 x.number * = 2 打印为 40 。

function fn(a = 1) {
    console.log(a);
}
fn();   //1
fn(undefined); //1
fn(null); //null
fn(false); //false 
function getItems(fruitList, ...args, favoriteFruit) {
return [...fruitList, ...args, favoriteFruit]
}
getItems(["banana", "apple"], "pear", "orange") //SyntaxError
//... args 是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。

箭头函数

  1. 没有自己的this,而是会继承上层作用域的this,就像其他普通的变量一样
  2. 不支持动态改变this值,所以不可以通过.call()、.apply()、.bind()方法来重新绑定它的this值
  3. 没有arguments对象过度追求
  4. “单行代码”写法可能会降低代码可读性箭头函数虽然表面上看是匿名的,但它可以根据前面的变量名和属性名自动推断出同名的name属性
  5. 不可以被new,也不会像普通函数一样自动拥有prototype属性
const Person = (name="wang",age=10) => {
    this.name = name;
    this.age = age;
    return this.name +' is '+ this.age + 'years old'
}
let result = new Person('zhang',11)
console.log(result) 
//这道题要注意哈,咋一看答案就是 zhang is 11  years old
//再认真看一下哈,这个构造函数是使用箭头函数的,所以肯定是报错啊。
let config = {
alert: setInterval(() => {
    console.log('Alert!')
}, 1000)
}
config = null
//setInterval 的回调仍然会被每秒钟调用

 一般情况下当我们将对象赋值为null , 那些对象会被进行 垃圾回收(garbage collected) 因为已经没有对这些对象的引用了。然而,setInterval 的参数是一个箭头函数(所以上下文绑定到对象 config 了),回调函数仍 然保留着对 config 的引用。只要存在引用,对象就不会被垃圾回收。因为没有被垃圾回收, setInterval 的 回调每1000ms (1s)会被调用一次。

const user = {
    email: "my@email.com",
    updateEmail: email => {
        this.email = email
    }
}
user.updateEmail("new@email.com")
console.log(user.email) //my@email.com

 updateEmail 函数是一个箭头函数,它没有和 user 对象绑定。这就意味着 this 关键字不会引用到 user 对象,但是会引用到全局对象。 user 对象内部的 email 的值不会更新。当打印 user.email 的时候, 原始 值 my@email.com 被返回。

 Setters

const config = {
languages: [],
set language(lang) {
return this.languages.push(lang);
}
};
console.log(config.language) // undefined
方法 language 是一个setter。Setters 并不保存一个实际值,它们的使命在于修改属性。当调用方法setter,返回 undefined 。

WebSocket的使用场景 ------------->高实时性

  1. 社交聊天
  2. 弹幕
  3. 多玩家游戏
  4. 协同编辑
  5. 股票基金实时报价
  6. 体育实况更新
  7. 视频会议/聊天
  8. 基于位置的应用
  9. 在线教育
  10. 智能家居

数组方法整理

  • 改变原数组

pop()、push()、shift()、unshift()、reverse()、sort()、splice()

  • 不改变原数组

concat()、join()、slice()、filter()、reduce()、find()、findIndex()

let newList = [1, 2, 3].push(4)

console.log(newList.push(5)) //Error
//push 方法返回数组的长度,而不是数组本身! 通过将 newList 设置为 [1,2,3].push(4) ,实际上 newList等于数组的新长度: 4 。
//然后,尝试在 newList 上使用 .push 方法。 由于 newList 是数值 4 ,抛出TypeError。

map()函数相关

let array = [,1,,2,,3];
array = array.map((i) => ++i) 
// [,2,,3,,4]
// map()会跳过空位,但会保留这个值
var arr = ["1", "2", "3", "4"];
var result = arr.map(parseInt);
console.log(result);
// [1,NaN,NaN,NaN]

// 等效于
var arr = ["1", "2", "3", "4"];
// var result = arr.map(parseInt);
var result = arr.map(function (val, index) {
return parseInt(val, index);
});
console.log(result);
//parseInt('1',0) // 任何整数以0为基数取整时,都会返回本身,所以这里返回的是1
//parseInt('2',1) //注意parseInt第二个参数的取值范围为2--36,所以不满足条件,这里只能返回NaN
//parseInt('3',2) // 表示将3作为二进制来进行处理,但是二进制只有0和1,所以3超出了范围,无法转换,返回`NaN`
//parseInt('4',3) //将4作为三进制来处理,但是4无法用三进制的数据表示,返回NaN

Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组

const person = {
name: "Lydia",
age: 21
}
for (const [x, y] of Object.entries(person)) {
console.log(x, y) //name Lydia and age 21
}
//[['name','Lydia'],['age',21]]
//使用 for-of 循环,我们可以迭代数组中的每个元素,上述情况是子数组。 我们可以使用 const [x,y] 在 forof 循环中解构子数组。 x 等于子数组中的第一个元素, y 等于子数组中的第二

Vue生命周期中父子组件顺序

加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

父beforeUpdate->父updated

销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

即使通讯方式

  1. 轮询
  2. 长轮询
  3. iframe流(长连接)
  4. websocket双向通信

逻辑与(&&)和逻辑或(||)

&&

当第一个条件为时,执行后面

当第一个条件为假时,不返回任何内容

||

当第一个条件为时,后面不执行

当第一个条件为假时,执行后面的

indexOf()不支持正则表达式

不支持冒泡的事件

  1. mouseenter
  2. mouseleave
  3. blur
  4. focus
  5. load
  6. unload
  7. resize

“俺(unload)”“妈(mouseenter) 妈(mouseleave) 不(blur) 让(resize) 浪(load) 费(focus)”

nodeType

  • 1:元素节点
  • 2:属性节点
  • 3:文本节点
  • 8:注释节点

NOSCRIPT标签

用来定义在脚本未被执行时的替代内容

Promise

const firstPromise = new Promise((res, rej) => {
setTimeout(res, 500, "one");
});
const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, "two");
});
Promise.race([firstPromise, secondPromise]).then(res => console.log(res)); //"two"

当我们向 Promise.race 方法中传入多个 Promise 时,会进行 优先 解析。在这个例子中,我们用 setTimeout给 firstPromise 和 secondPromise 分别设定了500ms和100ms的定时器。这意味着 secondPromise 会首先解析出字符串 two 。那么此时 res 参数即为 two ,是为输出结果

Promise.reject(0).catch(e => e).catch(e => console.log(e))
错误处理是只执行最近的一个catch的。所以只有第一个catch被执行了。
但是其实catch也是可以写成链的。那就是其中一个catch没能处理掉error,则抛出这个错误给下一个catch
const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')
const runPromises = async () => {
    const res1 = await Promise.all([promise1, promise2])
    const res2 = await Promise.all([promise3, promise4])
    return [res1, res2]
}
runPromises()
    .then(res => console.log(res))
    .catch(err => console.log(err))
//'Third'

 Promise.all 方法可以并行式运行promise。如果其中一个promise失败了, Promise.all 方法会带上被reject 的promise的值rejects。在这个例子中, promise3 带着 "Third" 值reject。我们在调用 runPromises 时在 runPromises 函数内部的 catch 方法去捕获任意error从而捕获到被reject的值。因为 promise3 带着 "Third" 被reject,所以只有 "Third" 打印。

 构造函数

function Car() {
this.make = "Lamborghini";
return { make: "Maserati" };
}
const myCar = new Car();
console.log(myCar.make); //"Maserati"
//返回属性的时候,属性的值等于 返回的 值,而不是构造函数中设定的值。
//我们返回了字符串 "Maserati" ,所以myCar.make 等于 "Maserati"

delete注意点

const name = "Lydia";
age = 21;
console.log(delete name); //false
console.log(delete age); //true
//delete 操作符返回一个布尔值:true 指删除成功,否则返回 false但是通过 var , const 或 let 关键字声明的变量无法用 delete 操作符来删除
//name 变量由 const 关键字声明,所以删除不成功:返回 false . 而我们设定 age 等于 21 时,我们实际上添加了一个名为 age 的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以 delete age 返回true

解构赋值

const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
console.log(y) // 1

JSON.stringify

const settings = {
username: "lydiahallie",
level: 19,
health: 90
};
const data = JSON.stringify(settings, ["level", "health"]);
console.log(data); //"{"level":19, "health":90}"

 JSON.stringify 的第二个参数是 替代者(replacer). 替代者(replacer)可以是个函数或数组,用以控制哪些值如何 被转换为字符串。

如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名 为 "level" 和 "health" 的属性被包括进来, "username" 则被排除在外。 data 就等于 "{"level":19, "health":90}" .

而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。 函数返回的值会成为这个属性的 值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有 异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为 undefined ,则该属性会被排除 在外。

字符串的padStart方法

const name = "Lydia Hallie"
console.log(name.padStart(13)) // " Lydia Hallie" , "Lydia Hallie" 
console.log(name.padStart(2)) //( "[1x whitespace]Lydia Hallie" , "Lydia Hallie" )

使用 padStart 方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。 字符串 Lydia Hallie 的长度为 12 , 因此 name.padStart(13) 在字符串的开头只会插入1( 13 - 12 = 1 ) 个空格。

如果传递给 padStart 方法的参数小于字符串的长度,则不会添加填充。

var a={}, b='123', c=123;
a[b]='b';  //a['123'] = 'b'
a[c]='c';  //a['123'] = 'c'
console.log(a[b]); // c


var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';  // a['Symbol('123')'] = 'b';
a[c]='c';  // a['Symbol('123')'] = 'c'
console.log(a[b]); //b




var a={}, b={key:'123'}, c={key:'456'};
a[b]='b'; // a['[object Object]'] = 'b';
a[c]='c'; // a['[object Object]'] = 'c';
console.log(a[b]); // c

 symbol的值都各不相同 唯一 所以不会被覆盖

对象的键名如果不是字符串的话 会调用tostring 方法 转换为 [object type] 相同 会进行覆盖

<input type="text" /> change 事件和input事件

  •  用户键入内容改变时,触发input事件,且在当标签失焦后,触发change事件

Number.isNaN()和isNaN()

const name = "Lydia Hallie";
const age = 21;
console.log(Number.isNaN(name)); // false
console.log(Number.isNaN(age)); //  false
console.log(isNaN(name)); // true
console.log(isNaN(age)); // false

//Number.isNaN ,你可以检测你传递的值是否为 数字值 并且是否等价于 NaN
//isNaN,你可以检测你传递的值是否一个 number

Class

class Bird {
    constructor() {
        console.log("I'm a bird")
      }
}
class Flamingo extends Bird {
    constructor() {
        console.log("I'm pink. 🌸");
        super();
    }
}
const pet = new Flamingo(); // I'm pink. 🌸 I'm a bird. 

我们创建了类 Flamingo 的实例 pet 。当我们实例化这个实例, Flamingo 中的 constructor 被调用。首先,输出 "I'm pink. 🌸" , 之后我们调用 super() 。 super() 调用父类的构造函数, Bird 。 Bird 的构造函数被调用,并输出 "I'm a bird.  “

class Calc {
    constructor() {
        this.count = 0
    }
    increase() {
        this.count ++
    }
}
const calc = new Calc()
new Calc().increase()
console.log(calc.count) //0

 我们设置 calc 变量为 Calc 类的一个新实例。 然后,我们初始化一个 Calc 的新实例,而且调用了这个实例 的 increase 方法。因为count属性是在 Calc class的constructor内部的,所以count属性不会在 Calc 的原 型链上共享出去。这就意味着calc实例的count值不会被更新,count仍然是 0 。

CSS

可以被继承的属性

  1. 文本(font-)
  2. 颜色(背景颜色不可以!)
  3. 列表(list-style-type)
  4. 元素可见性visibility

宽度计算

  1. ele.clientWidth = 宽度 + padding
  2. ele.offsetWidth = 宽度 + padding + border
  3.  ele.scrollTop = 被卷去的上侧距离
  4.  ele.scrollHeight = 自身实际的高度(不包括边框)
#container {
    width: 200px;
    height: 200px;
    padding: 20px;
    margin: 20px;
    border: solide 10px black;
}

 BFC

HTML元素要创建BFC,则满足下列的任意一个或多个条件

  1. float的值不是none。
  2. position的值不是static或者relative。
  3. display的值是inline-block、table-cell、flex、table-caption或者inline-flex
  4. overflow的值不是visible

BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。

<style type="text/css">
.a, .b, .c {
    box-sizing: border-box;
    border: 1px solid;
}
.wrap {
    width: 250px;
}
.a {
    width: 100px;
    height: 100px;
    float: left;
}
.b {
    width: 100px;
    height: 50px;
    float: left;
}
.c {
    width: 100px;
    height: 100px;
    display: inline-block;
}
</style>

<div class="wrap">
    <div class="a">a</div>
    <div class="b">b</div>
    <div class="c">c</div>
</div>
wrap 这个 div 的高度是多少   150px
display:inline-block会形成BFC,即块级格式化上下文,它是一个独立渲染的区域,并且与外部区域毫不相干,不会与浮动元素重叠。
因此会排在b后面,但是父盒子规定了宽度,所以就会飘下来。

meta元字符

width - viewport的宽度 
height - viewport的高度
initial-scale - 初始的缩放比例
minimum-scale - 允许用户缩放到的最小比例
maximum-scale - 允许用户缩放到的最大比例
user-scalable - 用户是否可以手动缩放

<a></a>标签属性

_blank         在新窗口打开链接

_self            在当前框架中打开链接

_parent        在父框架打开链接

_top             在当前窗口打开链接

framename  在指定框架打开链接

HTML中script标签,defer和async属性

defer(告诉浏览器不要等待脚本)

  • 具有 defer 特性的脚本不会阻塞页面。

  • 具有 defer 特性的脚本总是要等到 DOM 解析完毕,但在 DOMContentLoaded 事件之前执行

  • 脚本的执行是可以保证顺序的

async(脚本是完全独立的)

  • 浏览器不会因 async 脚本而阻塞(与 defer 类似)。

  • 其他脚本不会等待 async 脚本加载完成,同样,async 脚本也不会等待其他脚本

  • 脚本下载完成后会立即执行 并且是无序的

CSS 样式开启硬件加速 

transform: translateZ(0);

typescript是JS的超集,本质是增加了类型约束,类型推导

网络协议

ipv6报文头中的字段

版本号、流标签(flow label)、跳数限制

进程、线程、协程

  1. 拥有自己独立的堆和栈,既不共享堆,也不共享栈
  2. 线程是CPU独立运行和独立调度的基本单位
  3. 协程是一种用户态的轻量级线程
  4. 一个线程可以创建另外一个线程

TCP建立连接和断开连接时,客户端和服务端的变化

  1. SYN_SENT客户端发送SYN包之后的立即进入的状态,不用等待2ml
  2. 服务端收到客户端的SYN包后会进入SYN_RCVD状态,服务端收到ACK包后会进入established状态
  3.  当客户端处于ESTABLISHED状态时,服务端等待接收客户端的ACK,所以可能处于SYN_RCVD状态
  4. 客户端收到服务端确认包后,等待2*ml时间后会直接关闭连接。若没有收到,则不会关闭连接

交换机收到目的MAC为组播MAC的数据包将会学习源MAC

批处理系统的主要缺点是失去了交互性

常见状态码

  • 301 永久重定向
  • 302 临时重定向
  • 304 资源未被修改(去请求服务端,服务端告诉这个资源在本地还有效,不用再请求)
  • 401(未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应
  • 403 Forbidden: 服务器禁止访问,原因有很多,比如法律禁止、信息敏感、没有权限。
  • 404 资源未找到
  • 405: 请求方法不被服务器端允许。
  • 500: 仅仅告诉服务器出错了
  • 501: 表示客户端请求的功能还不支持。
  • 502: 服务器自身是正常的,但访问的时候出错了
  • 503: 表示服务器当前很忙,暂时无法响应服务。

HTTP请求方法

d08f4bcea1809d899e778428835b7993.png

加密算法

MD5

  1. 对称加密算法 
  2. 生成128位的字符串

RSA

  1. 非对称加密算法
  2. 允许选择公钥的大小

正则表达式

正则定义
\d匹配一个数字,等价于[0-9]
\w匹配字母、数字或者下划线,等价于 [A-Za-z0-9_]
\s匹配一个空白字符,包括空格、制表符、换页符和换行符
*匹配前一个表达式 0 次或多次
+匹配前面一个表达式 1 次或者多次
?匹配前一个表达式 0 次或1次

以下代码的执行后,str 的值是:
var str = "Hellllo world";
str = str.replace(/(l)\1/g, '$1');

(l)表示第一个分组里有l     \1表示所获取的第1个()匹配的引用   $1表示第一个分组里的值l

那么

(l)\1 表示匹配两个连续字符ll,即ll

(l)\l/g 表示全局匹配两个连续字符ll即llll

str.replace(/(l)\1/g, '$1') 表示将ll替换成l

3、最终

Hellllo => Hello

 数据结构

哈夫曼树计算

若以{4,5,6,7,8}作为叶子结点的权值构造哈夫曼树,则其带权路径长度是

  • 正序排列,然后从中选取两个最选的作为开端
  • 这里选择4,5

距离根节点距离

0            o

1       o         o

2   6    7    8      o

3                  4        5 

W=(4+5)*3+(6+7+8)*2=69

给定一组权值w={9, 12, 6, 3, 5, 15},其构成的哈夫曼树带权路径为

0                        o

1                  o           o

2              o    9    12   15

3          o     6

4       3    5

w = (3+5)*4 + 6*3 + (9+12+15)*2 = 32 + 18 + 72   .= 122

二叉树遍历

某二叉树的先序遍历序列为 ABDGCEFH,中序遍历序列为 DGBAECHF,则其后序遍历 序列是

先序ABDGCEFH

中序DGB|A|ECHF

个人习惯:根两边划分

先序:根左右

中序:左根右

后序:左右根

A为根,B,D,G都在A的左侧,ECHF都在A的右侧

即:

                  A

        B             C

D                 E       F

        G               H

GDBEHFCA

完全二叉树最大节点数

2^k-1 (k表示深度)

已知一棵完全二叉树的节点总数为11个, 则最后一层的节点数

深度应该是4,前3层共结点数2的3次方 -1 = 7, 11 - 7 等于4,所以最后一层结点数是4

数据结构的基本类型

  1. 线性结构
  2. 树形结构
  3. 图形结构

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值