CSS
disposition: fixed 是相对于屏幕视口 viewport 的位置来确定元素的位置;
css 属性 overflow 属性定义溢出元素内容区的内容会如何处理。如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制。
border:none以及border:0的区别?
当定义了border:none,即隐藏了边框的显示,实际就是边框宽度为0;
当定义边框时,必须定义边框的显示样式.因为边框默认样式为不显示 none ,所以仅设置边框宽度,由于样式不存在,边框的宽度也自动被设置为0。
border:0;浏览器对 border-width、border-color 进行渲染,占用内存。
border:none;浏览器不进行渲染,不占用内存。
JS
JS API eval:返回字符串表达式中的值
unEscape:返回字符串ASCI码
escape:返回字符的编码
parseFloat:返回实数
JS 中的数字在内存中占 8个 字节,64bit
JS 提供的全局函数:escape、unescape、eval、isFinite、isNaN、parseFloat、parseInt,setTimeout 是 window.setTimeout(由window提供)
事件队列,异步事件
js
// ------------------------------------------
for(var i=0; i<3; ++i){
setTimeout(function(){
console.log(i+''); // 输出3个3
}, 0);
}
// 避免的方法有两种
// 1
for(var i=0;i<5;++i){
(function(num){
setTimeout(function(){
console.log(num+ ' ');
}, 0);
})(i);
}
// 2: 用 let 替换 var 声明 i
for (let i = 0; i < 3; ++i) {
setTimeout( ()=>console.log('@ ', i), 0);
}闭包
js
// 情况1
function fn(){
var n = 0;
function add(){
n++;
console.log(n);
}
return {
n: n,
get: ()=> n,
add: add
}
}
var r1 = fn(); var r2 = fn(); r1.add(); r1.add();
console.log(r1.n);
r2.add();
// 输出:1 2 0 1, 第三个为什么不是 2
/* 情况2:如果 r1.n 是引用类型, 此时输出的值与前一个值相同 */
function fn(){
let obj = {};
obj.n = 0;
function add(){
obj.n++;
console.log(obj.n);
}
return {
n: obj, // 不能用 n: obj.n, 必须是引用类型,
add: add // 因为函数返回是按值传递(复制), 如果返回的是基本数据类型,
}
}
var r1 = fn(); var r2 = fn(); r1.add(); r1.add();
console.log(r1.n.n);
r2.add();
// 输出 1 2 2 1- 创建一个函数时,会创建一个作用域链,包含了该函数可以访问的作用域对象, 作用域链以数组的形式赋值给该函数的 [[Scopes]] 属性;例如当执行 fn() 时,会创建 add 函数,同时创建包含两个作用域对象的作用域链([[Scopes]] 数组有两个元素,Scopes[0] 代表的是外层函数 fn 的作用域对象,该对象只有 obj 一个属性;Scopes[1] 代表全局作用域对象);
- 调用函数 add 时,会为函数创建一个作用域(执行环境),然后复制 add 函数的 Scopes 属性值(基本数据类型与引用数据类型的区别),构建当前执行环境的作用域链,再将当前 add 函数的作用域对象加入到所构建的作用域链的前端,组成 add 函数所能访问的全部作用域对象。
- 第一种情况:
r1.n和fn内部的n不是同一个?; - 第二种情况:obj 是引用数据类型,复制后的 Scopes 的属性值中的 obj 与原来声明的 obj 是指向相同的内存空间,因此 obj.n++ 会影响到原来的数据;
参考:JS 高阶程序设计 P179、P181
各种方法实现
手写 Promise
实现 Array.reduce
js
Array.prototype._reduce = function(cb){
let ind = 0;
let len = this.length;
let initVal = null;
if(arguments.length > 1) initVal = arguments[1];
else{
while(ind < len && !this.hasOwnProperty(ind)){
ind++;
}
initVal = this[ind++];
}
for(; ind < len; ind++){
initVal = cb(initVal, this[ind], ind, this);
}
return initVal;
}Object.create
js
Object.create = function(proto) {
function _F() {}
_F.prototype = proto;
return new _F();
}多维数组平铺
js
function selfFlat(depth = 1){
let arr = [].slice.call(this);
if(depth === 0) return arr;
return arr.reduce((acc, cur) => {
if(Array.isArray(cur)){
// acc.concat(selfFlat.call(cur, depth-1));
return [...acc, ...selfFlat.call(cur, depth-1)]
}
else{
return acc = [...acc, cur];
}
}, []);
}
// 要求数组项不能包含逗号, 只能用逗号分隔
arr.join().split(',').map(i => print(i));快排
思路:
- xxx
js
function quickSort(array, left=0, right=array.length - 1) {
if (left < right) {
// 得到基准元素位置
pivotIndex = partition(array, left, right)
quickSort(array, left, pivotIndex - 1)
quickSort(array, pivotIndex + 1, right)
}
return array
}
function partition(array, left, right) {
// 取第一个位置的元素作为基准元素
const pivotValue = array[left]
while (left < right) {
/* 右边大于基准的数据不需要移动位置 */
/* 这里或下面的循环,一定要确保有一处把相等的情况包含在内 */
while (array[right] >= pivotValue && left < right) {
right--
}
/* 将右边第一个扫描到的小于基准的数据移动到左边的空位 */
array[left] = array[right];
/* 左边小于基准的数据不需要移动位置 */
while (array[left] < pivotValue && left < right) {
left++
}
array[right] = array[left]
}
/* 这里right和left 相等了 */
array[right] = pivotValue
return right
}
const arr = [9, 3, 12, 90, 32, 4, 12, 983, 2, 5, -9, -23, 49];
log(quickSort(arr.slice()))
log(arr.sort((a,b)=>a - b))数组排序并去重
js
function sortRemoveDuplicate(oriArr){
if(oriArr.length > 1){
let middleInd = Math.floor(oriArr.length / 2); // 数组中位数索引
let middleVal = oriArr.splice(middleInd, 1)[0]; // 提取数组中位数赋值给middleVal
// 相等时被过滤掉, 实现去重
let left = oriArr.filter( el => el < middleVal );
let right= oriArr.filter( el => el > middleVal );
let leftArr = sortRemoveDuplicate(left);
let rightArr = sortRemoveDuplicate(right);
// 为了消除函数执行过程中对函数名( sortRemoveDuplicate )的依赖, 可以使用下面的方式
// let leftArr = arguments.callee(left);
return leftArr.concat(middleVal, rightArr);
}else{
return oriArr;
}
}要点
- 二分法
- Array.splice
- 尾递归
函数柯里化
js
function curry(fn) {
if (fn.length <= 1) return fn;
let gene = (...args) => {
if (args.length >= fn.length) {
return fn(...args);
} else {
return (...arg2) => gene(...args, ...arg2);
}
}
return gene;
}
// 使用
function add(a, b, c, d) {
return a + b + c + d;
}
let curryed = curry(add);
print( curryed(1,2)(3)(4) );图像懒加载
img 的 src 属性先不赋值,监听滚动事件或 IntersectionObserver,当图像出现在视野中时才给 src 赋值。
js
<img src="./imgs/default.png" data="./imgs/1.png" alt="">
let imgs = document.querySelectorAll('img')
// 可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
function lazyLoad () {
// 滚动卷去的高度
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
for (let i = 0; i < imgs.length; i ++) {
// 得到图片顶部距离可视区顶部的距离
let x = clientHeight + scrollTop - imgs[i].offsetTop
// 图片在可视区内
if (x > 0 && x < clientHeight+imgs[i].height) {
imgs[i].src = imgs[i].getAttribute('data')
}
}
}
setInterval(lazyLoad, 1000)参考
字符串中不重复子串的长度的最大值
js
var lengthOfLongestSubstring = function(s) {
var start=0, end;
var len = s.length;
var hash = {};
var count = 0, max = 0;
if(len<2) return len;
hash[s[start]] = start;
count = 1;
for(end=start+1; end<len; end++){
if(typeof hash[s[end]] != 'undefined'){
console.log(hash);
max = count>max ? count : max;
var startBuf = hash[s[end]] + 1;
// 输出hash 表中的部分数据
for(var i=start; i<=hash[s[end]]; i++){
var ch = s[i];
delete hash[ch];
}
start = startBuf;
console.log(max);
} else {
count = end - start + 1;
}
hash[s[end]] = end;
}
max = count > max ? count : max;
return max;
};
lengthOfLongestSubstring('abcabcbb');网易

js
var N=0, M=0, works=[], A=null;
var i=0, lineArr=null
while(true){
i++;
lineArr = readline().split(' ');
if(i==1){
N = parseInt(lineArr[0]); M=parseInt(lineArr[1]);
}
else if(i>1 && i<=1+N){
works.push({
d: parseInt(lineArr[0]),
p: parseInt(lineArr[1])
});
}
else if(i==N+2){
A = lineArr;
break;
}
}
console.log('A:', A);
// 2 排序
fastSort(works, 0, works.length-1);
var j=0, ind = 0, len = works.length;
var result = 0;
for(i=0; i<len; i++){
ind = search(works, 0, len-1, parseInt(A[i]));
for(j=0; j<=ind; j++){
if(works[j].p > result) result = works[j].p;
}
console.log(result);
}
//console.log('ind: ',ind);
/*
*
*
*/
//排序
function fastSort(arr, start, end){
if(start==end) return;
var ind = part(arr, start, end);
// console.log(ind);
if(ind>start) fastSort(arr, start, ind-1);
if(ind<end) fastSort(arr, ind+1, end);
}
function part(arr, start, end){
if(end<start) return console.log('error: end<start!');
var ind = start, small=start-1;
for(; ind<end; ind++){
if(arr[ind].d<arr[end].d){
swap(ind, ++small);
}
}
swap(++small, end);
function swap(ind1, ind2){
var t=arr[ind1];
arr[ind1]=arr[ind2];
arr[ind2]=t;
}
return small;
}
// 3. 查找
function search(arr, start, end, target){
var len = arr.length;
var midInd = ((end-start+1)>>1) + start;
// console.log('midInd: ', midInd);
if(arr[midInd].d <= target){
if(midInd==(len-1) || arr[midInd+1].d > target) return midInd;
else return search(arr, midInd+1, end, target);
}
else if(midInd==0) return -2;
else return search(arr, start, midInd-1, target);
}