Appearance
盒子垂直水平居中
margin padding 百分比都是相对于父元素宽高的
- 子盒子
text-align:center;line-height:父盒子高度
- 定位:如果子盒子有宽高可以,top left 50%;margin top left: -50%; 如没有宽高 ,可以使用 css3
transform:translate(-50%,-50%)
- flex 弹性盒子:可以给父盒 设置
display: flex; justify-content: center; align-items: center;
- table: 父盒子,display:table; 子盒子:display: table-cell,text-align:center;vertical-align:center;
this 指向
js
// this指向
var fullName = 'a';
var obj = {
fullName: 'b',
prop: {
fullName: 'c',
getFullName: function () {
return this.fullName;
}
}
};
console.log(obj.prop.getFullName()); // c
var test = obj.prop.getFullName;
console.log(test()); // a
// 事件对列 2 3 5 4 1
setTimeout(() => {
console.log(1);
}, 0);
new Promise(function (resolve) {
console.log(2);
for (var i = 0; i < 10000; i++) {
i = 9999 && resolve();
}
console.log(3);
}).then(function () {
console.log(4);
});
console.log(5);
css 优先级
!important > 行内样式>ID 选择器>类选择器>标签选择器>通配符选择器> 继承>浏览器默认属性
初始位:0、0、0、0
行内选择符:1、0、0、0
ID 选择器:0、1、0、0
类选择器/属性选择器/伪类选择器:0、0、1、0
元素/伪元素: 0、0、0、1
var let const 的区别
- var 存在变量提升,没有块级作用域,相同作用域下,后都会覆盖前者
- let 、const 不存在变量提升、存在块级作用域、相同作用域下,不能重复申明
- const 声明时必须赋值
闭包
闭包一般指引用了另一个函数作用域中变量的函数,一般情况下在嵌套函数中实现的,可以直到变量保护,不会被全局污染
优点 1.可以读取函数内部的变量 2.可以让这些局部变量保存在内存中,实现变量数据共享。
缺点 1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
关于堆栈内存和闭包作用域的题
堆:存储引用类型值的空间;栈:存储基本类型值和指定代码的环境
js
// example1 => 对象和数组的区别
let a = {},
b = '0',
c = 0;
a[b] = 'hou';
a[c] = 'jian';
console.log(a[b]); // 'jian' 数字与字符串作为属性名不能重复
// example2 => 自己实现一个Symbol
let a = {},
b = Symbol('1'),
c = Symbol('1');
a[b] = 'hou';
a[c] = 'jian';
console.log(a[b]); // 'hou' Symbol('1') 是唯一值
// example3 => Object.prototype.toString() 检测数据类型 / valueOf 与 toString 的区别
let a = {},
b = { n: 1 },
c = { m: 2 };
a[b] = 'hou';
a[c] = 'jian';
console.log(a[b]); //'jian' a =》 {[object object]:'jian'} 变量做为属性名会调用 toString方法
// undefined null function 都可以做为属性名 内部运行都会调用 toString()
变量提升与函数提升
由此可见函数提升要比变量提升的优先级要高一些,且不会被变量声明覆盖,但是会被变量赋值之后覆盖。
函数声明要比函数表达式预解析优先级高
js
console.log(a);
console.log(a());
var a = 3;
function a() {
console.log(10);
}
console.log(a);
a = 6;
console.log(a());
// 预解析后
function a() {
console.log(10); // 10
}
var a;
console.log(a); // 函数表达式
console.log(a()); // undefined
a = 3;
console.log(a); // 3
a = 6;
console.log(a()); // Uncaught TypeError: a is not a function
// 输出顺序为 函数声明 10 undefined 3 TypeError
js
var test = (function (i) {
return function () {
alert((i *= 2));
};
})(2);
test(5); // 弹出结果是 字符串4 alert 会自动 toString()
js
var a = 0,
b = 0;
function A(a) {
A = function (b) {
console.log(a + b++);
};
console.log(a++);
}
A(1); // (a++) 输出1 局部的a =2
A(2); // (a + b++) 输出4 局部b =3
// 此时全局下的 a 和 b 没有改变
js
let obj = {
a: 100,
b: [10, 20, 30],
c: { x: 10 },
d: /^\d+$/
};
// 浅克隆 => obj中的包含的属性值是原始值修改不会影响obj2的的值,是引用类型的会影响obj2的值,因为它们指向同一个内存地址
// 正则表达式存储在栈中,页不是堆中, 只是复制了一份值,赋值给了变量
let obj2 = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
obj2[key] = obj[key];
}
}
let obj3 = { ...obj }; // 也是浅克隆
// 深克隆
let obj4 = JSON.parse(JSON.stringify(obj)); //对正则表达式 stringfy 会变成 {} 有弊端
实现 new 操作符
创建一个空对象,作为将要返回的实例
将空对象的原型指向构造函数的 prototype
将构造函数内部的 this 指向这个空对象
执行构造函数的内部代码
js
function Person(name, age) {
this.name = name;
this.age = age;
}
function _new() {
let args = Array.from(arguments);
let constructor = args.shift();
let context = Object.create(constructor.prototype);
let result = constructor.apply(obj, args);
return typeof result === 'object' && result != null ? result : context;
}
类型转换
空字符串、0、NaN、null、undefined 、 转换为 Boolean 类型都是 false,
空字符串、null、[] 转数字类型 =》0, undefined 、NaN =》NaN