IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 闭包内存回收和this的四个绑定规则 -> 正文阅读

[JavaScript知识库]闭包内存回收和this的四个绑定规则

闭包内存泄漏的案例:

function createFnArray () {
  // 占据的空间是4M
  var arr = new Array(1024 * 1024).fill(1)
  return function () {
    console.log(arr.length)
  }
}

var arrayFns = []
for (var i = 0; i < 100; i++) {
  arrayFns.push(createFnArray())
}

在内存的表现:

?销毁数据,避免内存泄漏的操作:

setTimeOut (() => {
    arrayFns = null
},2000)

  • AO对象不会被销毁时,是否里面的所有属性都不会被释放?
  1. 下面这段代码中name属于闭包的父作用域里面的变量
  2. 我们知道形成闭包之后count一定不会被销毁掉,那么name是否会被销毁掉呢?

代码:

function foo() {
  var name = 'why'
  var age = 18

  function bar() {
    debugger
    console.log(name)
  }
  return bar
}

var fn = foo()
fn()

?没有使用的age属性,js引擎会销毁这个age属性

为什么需要this?

有了this,我们编写代码更加方便

this在全局环境的指向:

在大多数情况下,this都是出现在函数中

在全局作用域下

浏览器:window(globalObject)

Node环境: {}

在函数中使用:

  • 所有的函数在被调用时,都会创建一个执行上下文
  • 这个上下文中记录着函数的调用栈,AO对象等
  • this也是其中的一条记录

this指向什么,跟函数所处的位置是没有关系的,跟函数被调用的方式是有关系

?默认绑定

独立函数调用

  • 独立的函数调用我们可以理解成函数没有被绑定到某一个对象上进行调用
  • 通过下面的案例看一下,常见的默认绑定:

// 默认绑定:独立函数调用
function foo () {
    console.log(this)
}

foo()

隐式绑定

调用方式是通过某个对象进行调用的

  • 也就是它的调用位置中,是通过某个对象发起的函数调用

  • ???????

?显示绑定

function foo () {
    console.log("函数被调用了",this)
}

// foo直接调用和call/apply调用的不同在于this绑定的不同
// foo直接调用指向的是全局对象(window)
// foo()

var obj = {
    name: "obj"
}

// call/apply是可以指定this的绑定对象的
foo.call(obj)
foo.apply(obj)
foo.apply("aaa")

call和apply有什么区别

?call和apply在执行函数时,是可以明确的绑定this,这个绑定规则称之为显示绑定

function sum(num1,num2,num3) {
  console.log(num1 + num2 + num3,this)
}
sum.call('call',20, 30, 40)
sum.apply('apply',[20, 30, 40])

显示绑定-bind

new绑定

  • JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字
  • 使用new关键字来调用时,会执行如下的操作:
  1. 创建一个全新的对象
  2. 这个新对象会被执行prototype连接
  3. 这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成)
  4. 如果函数没有返回其他对象,表达式会返回这个新对象

?内置函数的绑定思考

?规则优先级

  • 默认规则的优先级最低
  1. 毫无疑问,默认规则的优先级是最低的,因为存在其他规则时,就会通过其他规则的方式来绑定this
  • 显示绑定优先级高于隐式绑定
  • new绑定的优先级高于隐式绑定

new绑定 > 显式绑定(apply/call/bind) > 隐式绑定(obj.foo()) > 默认绑定(独立函数调用)

特殊绑定-忽略显式绑定

apply/call/bind: 当传入null、undefined时,自动将this绑定成全局对象

function foo() {
    console.log(this)
}

foo.apply('abc')
foo.apply({})

foo.apply(null)
foo.apply(undefined)

var bar = foo.bind(null)
bar()

?特殊绑定-间接函数引用

var obj1 = {
    name: "obj1",
    foo: function() {
        console.log(this)
    }
}

var obj2 = {
    name: "obj2"
};

(obj2.bar = obj1.foo)()

这里就是独立函数调用

箭头函数

箭头函数是ES6之后增加的一种编写函数的方法,并且它比函数表达式要更加简洁

  1. 箭头函数不会绑定this、arguments属性
  2. 箭头函数不能作为构造函数来使用(不i能和new一起来使用,会抛出错误)

// 1.编写箭头函数
// 1>(): 参数
// 2> =>:  箭头
// 3> {}: 函数的执行体
var foo = (num1, num2, num3) => {
  console.log(num1, num2, num3)
  var result = num1 + num2 + num3
  console.log(result)
}

function bar(num1, num2, num3) {

}

// 高阶函数在使用时,也可以传入箭头函数
var nums = [10, 20, 45, 78]
nums.forEach((item, index, arr) => {})

// 箭头函数有一些常见的简写:
// 简写一:如果参数只有一个,()可以省略
nums.forEach(item => {
  console.log(item)
})

// 简写二:如何函数执行体只有一行代码,那么{}也可以省略
// 强调:并且它会默认将这行代码的执行结构作为返回值
nums.forEach(item => console.log(item))
var newNums = nums.filter(item => item % 2 === 0)
console.log(newNums)

// filter/map/reduce
var result = nums.filter(item => item % 2 === 0)
                 .map(item => item * 100)
                 .reduce((preValue, item) => preValue + item)
console.log(result)

// 简写三:如果一个箭头函数,只有一行代码,并且返回一个对象,这个时候如何编写简写
var bar = () => {
  return {name: 'why', age: 18}
}

var bar = () => ({ name: 'why', age: 18})

箭头函数不使用this的四种标准规则(也就是不绑定this),而是根据外层作用域来决定this

?this面试题:

var name = "window";
var person = {
  name: "person",
  sayName: function () {
    console.log(this.name);
  }
};
function sayName() {
  var sss = person.sayName;
  sss(); 
  person.sayName(); 
  (person.sayName)(); 
  (b = person.sayName)(); 
}
sayName();

var name = 'window'
var person1 = {
  name: 'person1',
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person2 = { name: 'person2' }

person1.foo1(); 
person1.foo1.call(person2); 

person1.foo2();
person1.foo2.call(person2);

person1.foo3()();
person1.foo3.call(person2)();
person1.foo3().call(person2);

person1.foo4()();
person1.foo4.call(person2)();
person1.foo4().call(person2);
var name = 'window'
function Person (name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.foo1()
person1.foo1.call(person2)

person1.foo2()
person1.foo2.call(person2)

person1.foo3()()
person1.foo3.call(person2)()
person1.foo3().call(person2)

person1.foo4()()
person1.foo4.call(person2)()
person1.foo4().call(person2)
var name = 'window'
function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    foo1: function () {
      return function () {
        console.log(this.name)
      }
    },
    foo2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.obj.foo1()()
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)

person1.obj.foo2()()
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)

面试题的解析:

this指向https://mp.weixin.qq.com/s/hYm0JgBI25grNG_2sCRlTA

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-08 18:57:17  更:2022-06-08 18:58:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:27:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码