每日up

2018-7-28

1.谈谈JavaScript的垃圾回收机制

由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。 现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。

  • 标记清除:这是javascript中最常用的垃圾回收方式:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。工作流程:
    • 垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
    • 去掉环境中的变量以及被环境中的变量引用的变量的标记。
    • 再被加上标记的会被视为准备删除的变量。
    • 垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。
  • 另一种不太常见的垃圾回收策略是引用计数:工作原理:跟踪记录每个值被引用的次数。工作流程:
    • 声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。
    • 同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1.
    • 当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1.
    • 当引用次数变成0时,说明没办法访问这个值了。
    • 当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。

但是用这种方法存在着一个问题,下面来看看代码:

function problem() {
    var objA = new Object();
    var objB = new Object();
    objA.someOtherObject = objB;
    objB.anotherObject = objA;
}
复制代码

在这个例子中,objA和objB通过各自的属性相互引用;也就是说这两个对象的引用次数都是2。在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用域,函数执行完成之后,objA和objB还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露。

  • 什么情况会引起内存泄漏?

    虽然有垃圾回收机制但是我们编写代码操作不当还是会造成内存泄漏。

    • 意外的全局变量引起的内存泄漏。原因:全局变量,不会被回收。解决:使用严格模式避免。
    • 闭包引起的内存泄漏。原因:闭包可以维持函数内局部变量,使其得不到释放。解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
    • 没有清理的DOM元素引用。原因:虽然别的地方删除了,但是对象中还存在对dom的引用,解决:手动删除。
    • 被遗忘的定时器或者回调。原因:定时器中有dom的引用,即使dom删除了,但是定时器还在,所以内存中还是有这个dom。解决:手动删除定时器和dom。
    • 子元素存在引用引起的内存泄漏。原因:div中的ul li 得到这个div,会间接引用某个得到的li,那么此时因为div间接引用li,即使li被清空,也还是在内存中,并且只要li不被删除,他的父元素都不会被删除。解决:手动删除清空

2018-7-25

1.谈谈Cookie的弊端

  • Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉
  • 安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
  • 有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用

2.浅拷贝和深拷贝的区别

JavaScript的数据类型分为两大种:
  • 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
  • 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。
stack(栈)为自动分配的内存空间,它由系统自动释放;而heap(堆)则是动态分配的内存,大小不定也不会自动释放。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
基本类型与引用类型最大的区别实际就是传值与传址的区别。
    var a = [1,2,3,4,5];
    var b = a;
    var c = a[0];
    alert(b);//1,2,3,4,5
    alert(c);//1
    //改变数值        
    b[4] = 6;
    c = 7;
    alert(a[4]);//6
    alert(a[0]);//1
复制代码

JS 中的浅拷贝与深拷贝,只是针对复杂数据类型(Object,Array)的复制问题。浅拷贝与深拷贝都可以实现在已有对象上再生出一份的作用。但是对象的实例是存储在堆内存中然后通过一个引用值去操作对象,由此拷贝的时候就存在两种情况了:拷贝引用和拷贝实例,这也是浅拷贝和深拷贝的区别。

深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用

  • 浅拷贝:浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响
  • 深拷贝:在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响
浅拷贝 :所谓的浅复制,只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”
var a = {
  key1:"11111"
}
function Copy(p) {
  var c = {};
  for (var i in p) {
   c[i] = p[i];
  }
  return c;
}
a.key2 = ['小辉','小辉'];
var b = Copy(a);
b.key3 = '33333';
alert(b.key1);     //1111111
alert(b.key3);    //33333
alert(a.key3);    //undefined
b.key2.push("大辉");
alert(b.key2); //小辉,小辉,大辉
alert(a.key2); //小辉,小辉,大辉
复制代码

原因是key1的值属于基本类型,所以拷贝的时候传递的就是该数据段;但是key2的值是堆内存中的对象,所以key2在拷贝的时候传递的是指向key2对象的地址,无论复制多少个key2,其值始终是指向父对象的key2对象的内存空间。

深拷贝 :而深复制的话,我们要求复制一个复杂的对象,那么我们就可以利用递归的思想来做,及省性能,又不会发生引用。
function Copy(p, c) {
  var c = c || {};
  for (var i in p) {
    if (typeof p[i] === 'object') {
      c[i] = (p[i].constructor === Array) ? [] : {};
      Copy(p[i], c[i]);
    } else {
      c[i] = p[i];
    }
  }
  return c;
}    
a.key2 = ['小辉','小辉'];
var b={};
b = Copy(a,b);        
b.key2.push("大辉");
alert(b.key2);    //小辉,小辉,大辉
alert(a.key2);    //小辉,小辉
复制代码

2018-7-19

1.用javascipt写一个方法,模拟实现bind方法

来源https://blog.csdn.net/daimomo000/article/details/72897035

Function.prototype.bind2 = function (context) {

    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);
    var fNOP = function () {};

    var fbound = function () {
        self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
    }

    fNOP.prototype = this.prototype;
    fbound.prototype = new fNOP();

    return fbound;

}
复制代码

2.js哪些操作会实行隐式转换

  • 1 对象和布尔值比较

    对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字

[] == true; //false []转换为字符串'',然后转换为数字0,true转换为数字1,所以为false
复制代码
  • 2 对象和字符串比较

    对象和字符串进行比较时,对象转换为字符串,然后两者进行比较。

[1,2,3] == '1,2,3' // true [1,2,3]转化为'1,2,3',然后和'1,2,3', so结果为true;
复制代码
  • 3 对象和数字比较

    对象和数字进行比较时,对象先转换为字符串,然后转换为数字,再和数字进行比较。

[1] == 1; // true `对象先转换为字符串再转换为数字,二者再比较 [1] => '1' => 1 所以结果为true
复制代码
  • 4 字符串和数字比较

    字符串和数字进行比较时,字符串转换成数字,二者再比较。

'1' == 1 // true
复制代码
  • 5 字符串和布尔值比较

    字符串和布尔值进行比较时,二者全部转换成数值再比较。

'1' == true; // true
复制代码
  • 6 布尔值和数字比较

    布尔值和数字进行比较时,布尔转换为数字,二者比较。

true == 1 // true
复制代码

任意两种类型比较时,如果不是同一个类型比较的话,则按如图方式进行相应类型转换,如对象和布尔比较的话,对象 => 字符串 => 数值 布尔值 => 数值。

3.浏览器标准模式和怪异模式之间的区别是什么

在HTML与CSS的标准化未完成之前,各个浏览器对于HTML和CSS的解析有各自不同的实现,而有很多旧的网页都是按照这些非标准的实现去设计的。在HTML与CSS标准确定之后,浏览器一方面要按照标准去实现对HTML与CSS的支持,另一方面又要保证对非标准的旧网页设计的后向兼容性。因此,现代的浏览器一般都有两种渲染模式:标准模式和怪异模式。在标准模式下,浏览器按照HTML与CSS标准对文档进行解析和渲染;而在怪异模式下,浏览器则按照旧有的非标准的实现方式对文档进行解析和渲染。

区别
  • 盒模型:IE下标准模式为:content+padding+border+margin。怪异模式下为:content+margin(padding,border包含在content宽高中)
  • 怪异模式中IE6/7/8都不识别!important声明
  • 设置行内元素宽高,标准模式下不生效,怪异模式下生效
  • margin:0 auto,在标准模式下会水平居中,怪异模式下不会。

4.声明式函数和表达式函数的区别

定义函数有两种方式:函数声明和函数表达式。

函数声明
function functionName(arg0,arg1){
//函数体
}
复制代码
函数表达式
a();
function a(){alert("a");}
//a
复制代码
  • 函数声明中函数名是必须的,函数表达式中则是可选的
  • 用函数声明定义的函数,函数可以在函数声明之前调用,而用函数表达式定义的函数则只能在声明之后调用。

2018-7-18

1.实现函数fn(2)(4) == 8

function fn(x){
    return function(y){
        return x*y
    }
}
复制代码

2.vue共有多少个生命周期函数

  • beforeCreate 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用
  • created 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
  • beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用
  • mounted el被新创建的 vm.el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.el 也在文档内。
  • beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
  • updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
  • activated keep-alive 组件激活时调用。
  • deactivated keep-alive 组件停用时调用。
  • beforeDestory 实例销毁之前调用。在这一步,实例仍然完全可用。
  • destoryed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
  • errorCaptrued

3.原型和原型链

  • 原型链的原理:
__proto__ = constructor.prototype
复制代码

只有函数才有prototype属性并且可以访问到,但是对象实例不具有该属性,只有一个内部的不可访问的__proto__属性。__proto__是对象中一个指向相关原型的神秘链接。按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

  • 原型对象

每创建一个函数都会有一个prototype属性,这个属性是一个指针,指向一个对象(通过该构造函数创建实例对象的原型对象)。原型对象是包含特定类型的所有实例共享的属性和方法。原型对象的好处是,可以让所有实例对象共享它所包含的属性和方法。(原型对象属于普通对象。Function.prototype是个例外,它是原型对象,却又是函数对象,作为一个函数对象,它又没有prototype属性。)

  • 原型链

在JavaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。)

原型对象(Person.prototype)是 构造函数(Person)的一个实例。

function Animal(){  
  this.type = "animal";  
}  
Animal.prototype.getType = function(){  
  return this.type;  
}  
function Dog(){  
  this.name = "dog";  
}  
Dog.prototype = new Animal();    
Dog.prototype.getName = function(){  
  return this.name;  
}   
var xiaohuang = new Dog();  
//原型链关系  
xiaohuang.__proto__ === Dog.prototype  
Dog.prototype.__proto__ === Animal.prototype  
Animal.prototype.__proto__ === Object.prototype  
Object.prototype.__proto__ === null

复制代码

4.vue每个生命周期的作用(同上2)

5.position有几个属性,作用

  • absolute: 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
  • fixed :生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
  • relative: 生成相对定位的元素,相对于其正常位置进行定位。因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。
  • static :默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)
  • inherit: 规定应该从父元素继承 position 属性的值。
  • unset:名如其意,unset 关键字我们可以简单理解为不设置。其实,它是关键字 initial 和 inherit 的组合。什么意思呢?也就是当我们给一个 CSS 属性设置了 unset 的话:如果该属性是默认继承属性,该值等同于 inherit, 如果该属性是非继承属性,该值等同于 initial
  • sticky: 设置了sticky的元素,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。

(当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,不再向上移动。)

sticky属性生效的条件有以下两点:

- 是元素自身在文档流中的位置
- 一个是该元素的父容器的边缘
复制代码

转载于:https://juejin.im/post/5b4ee3006fb9a04f8856cd8d

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值