Js进阶1

(一) 基本数据类型和引用数据类型的区别

基本数据类型和引用数据类型数据在内存中的存储

  • 基本数据类型存放在 栈区

  • 引用数据类型存放在 堆区, 同时在栈区存放数据,在堆区存放的地址(引用)

(二) 函数的调用方式

1.普通函数的调用, 函数名();

2.回调函数:

// 回调函数: 函数作为参数
// callback是个函数
function foo(callback) {
  callback(100); // callback就是goo(100)
} 
function goo(num) {
  console.log(num);
} 
foo(goo); 

回调函数是一个作为变量传递给另外一个函数的函数,它在主体函数执行完之后执行。

function A有一个参数function B,function B会在function A执行完成之后被调用执行。

3.递归函数

// 递归是指函数自己调用自己
function say() {
  say();
}
// 不使用for循环进行数字累加 
var sum = 0;
function add(i) {
  sum = sum + i;
  console.log(sum);
  ++i;
  if (i <= 100) {
    add(i);
  }
}
add(1);

4.自调函数

// 自调用:可以避免全局变量污染
(function(c){
  var a = 100;
  var b = 200;
  console.log(c);
})(300); 

(三) js垃圾回收机制#

垃圾回收机制是什么#

垃圾回收机制(GC:Garbage Collection),执行环境负责管理代码执行过程中使用的内存。垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。

垃圾回收策略是什么#

2种最为常用:标记清除和引用计数,其中标记清除更为常用。

标记清除(mark-and-sweep):是对于脱离作用域的变量进行回收,当进入作用域时,进行标记,离开作用域时,标记并回收这些变量。到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。 当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入相应的环境,就可能用到它们。而当变量离开环境时,这将其 标记为“离开环境”。

引用计数:引用计数是跟踪记录每个值被引用的次数。就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。引用计数方法可能导致循环引用,类似死锁,导致内存泄露。

如何减少垃圾回收开销#

由于每次的垃圾回收开销都相对较大,并且由于机制的一些不完善的地方,可能会导致内存泄露,我们可以利用一些方法减少垃圾回收,并且尽量避免循环引用。

  1. 在对象结束使用后 ,令obj = null。这样利于解除循环引用,使得无用变量及时被回收;

  2. js中开辟空间的操作有new XX() 比如new Date() , [ ], { }, function (){..}。尽量减少此类操作, 最大限度的实现对象的重用;举例:

  3. 慎用闭包。闭包容易引起内存泄露。本来在函数返回之后,之前的空间都会被回收。但是由于闭包可能保存着函数内部变量的引用,且闭包在外部环境,就会导致函数内部的变量不能够销毁。

 var arr = [1,2,3,4];
 arr = []; // 清空数组-不好的做法
 arr.length = 0;  // 清空数组,好的做法

如何优化垃圾回收#

分代回收(Generation GC):与Java回收策略思想是一致的。目的是通过区分“临时”与“持久”对象;多回收“临时对象”区(young generation),少回收“持久对象”区(tenured generation),减少每次需遍历的对象,从而减少每次GC的耗时。 增量GC:这个方案的思想很简单,就是“每次处理一点,下次再处理一点,如此类推。

(四) js异步编程#

(1) 同步和异步(理解)#

js中的同步和异步跟生活中的同步异步意思有些不太一样

js的同步指的是,同一时间只执行一个任务, 当一个任务结束以后才能执行下一个任务。

js的异步指的是,同一时间可以执行多个任务,常见的js异步操作有setTimeout(), setInterval(), ajax请求等。

(2) 单线程和多线程(理解)#

单线程: 同一时间只能做一件事 多线程: 同一时间可以做多件事 JavaScript语言的一大特点就是单线程, 那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。比如java和c#就是多线程的语言。 JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准? 所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

(3) JS中的异步运行机制#

也称js事件循环机制(Event Loop)
JS是单线程的,那么他是如何是实现异步操作的? JS中的异步运行机制(背诵):

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件(事件一般都有对应的回调函数)。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行任务(实际上就是执行任务对应的回调函数)。

(4)主线程不断重复上面的前三步。

(五) this的指向#

问题:谈谈this的指向(背诵) 或问:解释下JavaScript中this是如何工作

答: this的指向有以下几种情况

​ 注意: this永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。

  1. 普通的函数调用: 函数被谁调用,this就是谁。
  2. 匿名函数或不处于任何对象中的函数指向window 。
  3. 如果是call, apply, bind,this指向了这三者调用函数时传入的第一个参数
  4. 构造函数中的this, 直接调用函数this的指向同第1点, 使用new操作符, this指向构造函数所创建的实例对象
  5. 箭头函数的指向: 由于箭头函数不绑定this, 父级元素的this指向, 作为自己的this值

(1) 普通的函数调用#

函数被谁调用,this就是谁

 <!DOCTYPE html>
<html lang="en">
 
<body> 

    <script>
       function say() {
           console.log('this:',this);
       } 
       say(); // 实际是: window.say(), 所以this指向window


       var person = {
           name: '张三',
           sayName: function() {
               console.log('this',this);
           }
       }
       person.sayName();  // person调用了sayName,
    </script>
</body> 
</html>

 (2) 匿名函数或不处于任何对象中的函数指向window

var person = {
    name: '张三',
    say: function () {
        setTimeout(function() {
            console.log(this);
        },1000);
    }
}

person.say(); 

(3) call, apply, bind的指向

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值