1.闭包
let 形成闭包 var全局变量
function test() {for (var i = 0; i < 6; i++) {console.log(i); //1 2 3 4 5 6// setTimeout(() => {// console.log(i);// }, 0); 6 6 6 6 6 6 6}
}
test();var array = [];
for (var i = 0; i < 3; i++) {array.push(() => i);
}
var newArray = array.map((el) => el());
console.log(newArray); //[3,3,3]
闭包的引用问题
2.W3C标准盒子模型和IE盒子模型的区别
IE5.5及更早的版本使用的是IE盒模型。IE6及其以上的版本在标准兼容模式下使用的是W3C的盒模型标准。box-sizing属性可以切换盒模型模式,默认值是content-box,可选择有border-box、inherit。
- content-box:w3c标准盒模型。盒子实际大小取决于width+padding+border+margin
- border-box:IE盒模型,怪异盒模型。盒子实际大小取决于width+margin
- inherit:从父元素集成box-sizing属性的值
3.HTTP请求方法
get与post的区别
(1)post更安全(GET把参数包含在URL中,POST通过request body传递参数;get请求的数据会被缓存,如果两次传输的数据相同,第二次传输的数据时间大约为10ms;)
(2)post发送的数据更大(get有url长度限制)
(3)post能发送更多的数据类型(get只能发送ASCII字符)
(4)post比get慢。post在真正接收数据之前,会先将请求头发送给服务器进行确认,然后才真正发送数据。即tcp三次握手后服务器返回100 Continue响应,浏览器再发送数据,服务器返回200 OK响应。
(5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作,目的是资源的获取,读取数据
请求的方法
4.map
map的方法,set,get,has
let test = new Map();
test.set(3); //{3:undefined}
console.log(typeof null); //Object
Map对象和普通对象的7个区别
1、初始化与使用
普通对象可以直接使用字面量进行初始化,而 Map 需要 Map() 构造函数进行初始化,如果想要有初始值,则需要传递一个数组或其他元素为键值对的可迭代对象。
const obj = {name: 1,age: 2,
};const map = new Map([['name', 1],['age', 2],
]);
使用,各自拥有获取键值,设置键值,判断存在键值。但是Map拥有 size属性可以返回当前Map中key/value对的数量,而普通对象需要手动计算使用自己的方法Object.keys(obj).length。
2、key类型
普通对象只接受字符串和符号作为键值,其他类型将被强制转换为字符串类型,而 Map 可以接受任何类型的键值(包括函数、对象或任何原语)。
const obj = {};
const map = new Map();
const key = function () {};
obj[key] = 1;
map.set(key, 1);// { 'function () {}': 1 }
console.log('obj: ', obj);// Map(1) { [Function: key] => 1 }
console.log('map: ', map);
3、继承
普通对象从原型继承了许多属性键,例如构造函数等。因此,自己的键值很可能与原型上的密钥发生冲突。但是 Map 默认不包含任何键
4、插入顺序
Map 元素的顺序遵循插入的顺序,而 Object 的则没有这一特性。
5、迭代
使用 for...of 语句或 Map.forEach 直接迭代 Map 的属性,而普通对象for...in
6、序列化
普通对象支持 JSON 序列化,但 Map 默认无法获取正确数据。
7、性能
Map 对象在涉及频繁添加和删除键值对的场景中表现更好,而普通对象没有优化。
Map 和 WeakMap 区别
WeakMap是 ES6 中新增的一种集合类型,叫做“弱映射”。它和Map是兄弟关系,与Map的区别就在于这个弱字,API 还是Map的那套(只有set get has delete)。WeakMap 其实描述的是 JS 中垃圾回收程序对待“弱映射”中键的方式
1、WeakMap 的特性
WeakMap 只能将对象作为键名
WeakMap 的键名引用的对象是弱引用
WeakMap 不可遍历
2、Map 和 WeakMap 区别
Map 的键可以是任意类型,WeakMap 只接受对象作为键(null除外),不接受其他类型的值作为键
Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键; WeakMap 的键是弱引用,键所指向的对象可以被垃圾回收,此时键是无效的
Map 可以被遍历, WeakMap 不能被遍历
3、WeakMap 的使用场景
DOM 节点元数据
部署私有属性
数据缓存
5.时间
getDay() 返回的是星期几(0~6);获取4位数年份要用getFullYear() ;get Month() 返回的值是0~11。D正确
5.undefined情况
变量没赋值时默认值是undefined
函数默认的返回值也是undefined
不存在的数组元素或者对象属性也是undefined
6.typeof
let obj = { 1: 12, 2: 22 };
for (key in obj) {console.log(key);
}
let fun = function () {};
let arr = [];
console.log(typeof null); //object
console.log(typeof fun); //function
console.log(typeof arr);//object
console.log(typeof {});//object
var x = typeof x; //x--undefined
var res = typeof typeof x; //string
// var res = typeof undefined; //undefined
console.log(x, res);
console.log(typeof typeof 0); //string
7.重排与回流
重排:重新计算元素的大小,重新渲染
回流:不用重新计算,只需重新渲染
减少重排与回流:动画用定位,添加类名或一次性直接修改样式,样式与html不进行深度嵌套
8.定时器的回调
function fn() {console.log("111");
}
// setTimeout(() => {
// fn();
// }, 0);
setTimeout(fn, 0);
8.promise
reject
promise中的reject函数返回值不一定会报错,传到catch中,需要看then函数中,有多少个回调函数,只有一个的话,就会报错,传到catch中,有两个的话,就会传到then的第二个回调函数的参数中。
var p1 = new Promise((res, rej) => {rej(1);
});
p1.then((value) => console.log("then的第一个回调函数res", value),(params) => console.log("then的第二个回调函数params", params)
).catch((err) => console.log("catch回调函数err", err));//then的第二个回调函数params 1
Promise.all
Promise.all([ ])中,数组为空数组,则立即决议为成功执行resolve( );
Promise.race([ ])中数组为空数组,就不会执行,永远挂起,不会执行resolve( );
Promise.all
Promise.race
如果希望在多个Promise对象同时执行时,只要有一个Promise对象的状态发生改变就中断执行,可以使用Promise.race()
方法,该方法接收一个Promise数组作为参数,并返回一个新的Promise对象,当其中任何一个Promise对象被解决或拒绝时,就会将其对应的值或原因传递给返回的Promise对象的回调函数。我们可以在then回调函数中检查Promise对象的状态以及返回值,然后进行相应的处理。
Promise.race([promise1, promise2, promise3]).then(result => {console.log(result);}).catch(error => {console.error(error);});
pedding fullfilled reject
9.结构赋值,剩余参数...rest,参数数组arguments,对象属性简写
let [a, b, c, d, e] = "hello";
console.log(a, b, c, d, e);
//h e l l o
10.原型对象
参考:JavaScript构造函数和原型、原型链及this指向_this.constructor_遥岑.的博客-CSDN博客
原型对象 构造函数 对象
1.对象都会有一个属性__proto__指向构造函数的prototype原型对象
2.构造函数原型对象(prototype)里面都有一个constructor属性
- 一般情况下,我们的公共属性定义在构造函数里面,公共的方法放在原型对象身上
- 如果方法放在构造函数里面,创建实例时都会为这个方法单独再开辟一块内存空间来存放同一个函数,浪费内存
解决方法:公共方法放在原型对象身上,这样所有实例可以共享方法
疑惑点,对象如何访问构造函数的属性?原型对象如何获取对象的属性?
class Father {constructor(name, age) {this.name = name;this.age = age;}try = () => {console.log(this.games);};
}
Father.prototype.eat = function () {console.log(this.name + "会跑");
}; //原型对象添加方法
Father.prototype.games = "游戏人生";
let p1 = new Father("p1", 38);
p1.eat(); //p1会跑
p1.try();//游戏人生
原型链
var Foo = (function () {var x = 0;function Foo() {}Foo.prototype.increment = function () {++x;console.log(x);};return Foo;
})();var a = new Foo();a.increment();
a.increment();
var b = new Foo();
b.increment();
//1 2 3
最讨厌 这些new。。。,我都不知道创建了啥
new test.getName();
new test().getName();
new new test().getName();
function test() {getName = function () {Promise.resolve().then(() => console.log(0));console.log(1);};return this;
}
test.getName = function () {setTimeout(() => console.log(2), 0);console.log(3);
};
test.prototype.getName = function () {console.log(4);
};
var getName = function () {console.log(5);
};
function getName() {console.log(6);
}test.getName(); //3 2
console.log("-------");
getName(); //5
new test().getName(); //4
console.log("-------");
getName(); //1 0
console.log("-------");
new test.getName(); //3 2
new test().getName(); //4
new new test().getName(); //4
11.css
12.逻辑
console.log(2 < 3 || 3 < 2); //true
console.log(true || 1); //true
console.log(false || 2); //2
console.log(true && 3); //3
console.log(false && 4); //false
console.log(true || (false && false), (true && false) || true); //true true
13.js基础
console.log(1 + -+(+(+-+1))); //1
let arr = ["a", , "b", ,];
console.log(arr, arr.length);
//[ 'a', <1 empty item>, 'b', <1 empty item> ] 4//length方法可以截断及清空数组,而不能操作字符串。
var str = "我非常喜欢编程";
str.length = 3; //我非常喜欢编程
str.length = 14; //我非常喜欢编程
console.log(str);
var test = [1, 2, 3, 4];
// test.length = 1; //1
test.length = 7; //[ 1, 2, 3, 4, <3 empty items> ]
console.log(test);console.log("a" - 1); //NaN
console.log("5" - 1); //4function 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("Case default");}
}
showCase(new String("A")); //Case default
showCase(String("A")); //Case A
14.数组
push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
var a = []; // [ ]
a.push(1, 2); // [1,2] 数组末尾添加 1,2
a.shift(3, 4); // [ 2 ] shift()会删除数组的第一个元素,里面写啥都没用
a.concat([5, 6]); // [2] 拼接数组,会返回新的数组,这里没接收返回的新数组 ,a没变
a.splice(0, 1, 3); // [3] 删除下标为0的元素,同时替换为 2
15.对象
// example 1
var a = {},b = "123",c = 123;
a[b] = "b";
a[c] = "c";
console.log(a[b]); //c
console.log(a); //{ '123': 'c' }// example =2
var a = {},b = { key: "123" },c = { key: "456" };
a[b] = "b";
a[c] = "c";
console.log(a[b]); //c
console.log(a); //{ '[object Object]': 'c' }// example =3
console.log(Function instanceof Object); //true
console.log(Object instanceof Function); //true// example =4
var b = {age: 11,
};
var arr = [1, 2];
function test(a, y) {a[0] = 10;--y.age;
}
test(arr, b);
console.log(arr); //[ 10, 2 ]
console.log(b); //{ age: 10 }
16.深入理解this
call,bind,apply
- apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
- call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
- bind除了返回函数以外,它的参数和call 一样。
call 与 apply 的相同点:
- 方法的含义是一样的,即方法功能是一样的;
- 第一个参数的作用是一样的;
call 与 apply 的不同点:两者传入的列表形式不一样
- call可以传入多个参数;
- apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入
var x = 1;var obj = {x: 3,fun: function () {var x = 5;return this.x;},
};var fun = obj.fun;
console.log(obj.fun(), fun()); //3 undefined//非严格模式this为window,严格模式 undefined。node为严格模式// log1
let obj1 = {a: 1,foo: () => {console.log(this.a);},
};
obj1.foo();
const obj2 = obj1.foo;
obj2();//undefined,调用者为window// log2
var obj = {a: 1,foo: function () {setTimeout(function () {console.log(this.a), 3000;});},
};
obj.foo(); //undefined,调用者为window
function fun() {return () => {return () => {return () => {console.log(this.name);};};};
}
var f = fun.call({ name: "foo" });
// 因为t1、t2、t3都是箭头函数,使用call()方法不能改变this指向,
// 作用域链上最近的this还是指向{name:‘foo’}。
var t1 = f.call({ name: "bar" })()(); //foo
var t2 = f().call({ name: "baz" })(); //foo
var t3 = f()().call({ name: "qux" }); //foofunction fun() {return function () {return function () {return function () {console.log(this.name);};};};
}
var f = fun.call({ name: "foo" });
var t1 = f.call({ name: "bar" })()(); //undefined
var t2 = f().call({ name: "baz" })(); //undefined
var t3 = f()().call({ name: "qux" }); //qux
var name = "global";var obj = {name: "local",foo: function() {this.name = "foo";}.bind(window),};var bar = new obj.foo(); //{name:"foo";}setTimeout(function() {console.log("11", window.name); //global}, 0);console.log(bar.name); //foovar bar3 = (bar2 = bar);bar2.name = "foo2";console.log(bar3.name); //foo2
17.正则
var s = "12ab3cd",arr = s.split(/\d+/);
console.log(arr); //[ '', '', 'ab', 'cd' ]
// arr = s.split(/\d+/); //[ '', 'ab', 'cd' ]
18.事件循环
setTimeout(() => {console.log(1);
}, 0);const P = new Promise((resolve, reject) => {console.log(2);setTimeout(() => {resolve(); //2 5 1 3 4console.log(3);}, 0);// resolve(); //2 5 4 1 3
});P.then(() => {console.log(4);
});
console.log(5);
19.作用域与预编译
var foo = "Hello";
(function () {var bar = " World";console.log(foo + bar); //Hello World
})();
console.log(foo + bar); //报错