从问题入手
学习知识基础是关键。在此记录关键问题,不断丰富。仅供自己学习。
问题
- js内存分几类?分别用来存放什么?
- 全局作用域和私有作用域
- 内存释放
- 什么叫预解释?
- 全局变量和私有变量
- 函数执行基本顺序
- 代码执行变量获取顺序
- 解释闭包
- this的指向
- 前端常接触的设计模式
- var n1 = new Number和var n2 = 1有什么不同?var a1 = new Array和var a2 = []有什么不同?
- 解释一下js的原型链
答
- js内存分几类?分别用来存放什么?
answer:js分为栈内存和堆内存
堆内存用来存放引用数据类型的具体内容,object类型存储key value;function类型用来存放函数内容的字符串
栈内存用来提供一个js代码执行的环境。全局作用域和私有作用域都属于栈内存。
- 全局作用域和私有作用域?
answer:
全局作用域:浏览器一打开就创建,浏览器关闭时才销毁。 私有作用域:函数执行才产生私有作用域。
- 内存释放?
answer:
堆内存释放:引用数据类型定义的时候开辟一个新的堆内存,该内存有个引用地址。如果存在变量引用该地址,则内存被占用不可销毁。若想释放,则把他的内存指向null,当前堆内存没有被占用,则浏览器会在空闲时销毁。
栈内存释放:全局作用域浏览器一打开即创建,关闭才销毁。私有作用域,函数执行时产生,私有作用域的代码执行完了,则当前作用域被销毁。
但是,当前私有作用域的部分内容被当前作用域之外的内容占用了,当前作用域不能销毁。
- 函数执行返回一个引用数据类型的值,并且在函数外被接收了。这种情况行程的私有作用域不会被销毁,比如返回一个函数、对象、数组、则该堆内存无法释放,与此同时,执行该堆内存的执行栈内存也无法释放。但是返回数字,字符串,布尔值,则直接返回值,函数执行产生的私有作用域执行一次销毁一次。
- 私有作用域中进行dom事件绑定,因为dom事件绑定,则该私有作用域也不能释放(dom绑定相当于返回一个函数,和情况1本质相同)。
- 函数执行返回的函数并没有被其余变量接收,但是会紧接着执行一次,则该内存不会立即销毁,在执行完毕后再销毁。
function fn(){ var num = 100; return function(){ }}fn()()复制代码
- 什么叫预解释?
answer:也叫变量提升。在当前作用域中,js代码执行之前,浏览器首先会把带var 和 function 的进行提前声明或定义。(var 声明 function 声明+定义)
预解释只发生在当前作用域下,开始只对window下(全局作用域)下预解释,函数执行时对(私有作用域)下进行预解释。全局和私有作用域都存在预解释。
- 全局变量和私有变量?
answer:
全局变量:全局作用域下定义的变量(全局下预解释)
私有变量:私有作用域中声明的变量 和 函数的形参。
- 函数执行基本顺序?
answer:
- 生成一个新的私有作用域
- 如果有形参,先形参赋值
- 在私有作用域中进行预解释
- 在私有作用域中从上到下执行代码
- 函数执行变量获取顺序?
answer:
- 先确定私有变量中是否存在(形参+声明的私有变量),如果有优先使用私有变量。
- 如果没有则向上级作用域查找,直到window为止。
- 上级作用域只和函数定义有关,和在哪执行无关。在哪个作用域下定义的,上级作用域就是谁。
- 解释闭包?
answer:闭包是一种机制,函数执行时产生的私有作用域内的变量保护起来,不受外界干扰。
- this的指向?
answer:仅代表当前行为的执行主体
和的当前执行的环境(区域)上下文无关; 和函数在哪定义,在哪执行无关;
- 函数执行,函数名前面有.则.前面为this;没有.window为this;
- 自执行函数中,this永远指向window;
- 给dom元素绑定事件,当前事件触发执行绑定方法,方法中的this执行当前dom元素。
- 构造函数模式中,函数体中(类中)的this中,指向当前类的一个实例。
- 前端常接触的设计模式 answer:
- 单例模式:分组编写各自的功能模块。
- 工厂模式:相同功能代码,抽取到一个函数处理。
- 构造函数模式:创建类,并利用类的实例。
function Fn(){ this.x = 100;}Fn.prototype.getX = function(){};var f1 = new Fn复制代码
构造函数模式注意点:1. 不需要传参时,()可以省略。2. 构造函数中的this指向某个实例,但是属性值内包含this,需要看.前面的内容。复制代码
function Fn(){ this.x = 100; this.getX = function(){ console.log(this.x) }}var f1 = new Fn复制代码
3. 构造函数里的var只是私有变量而已,和类、实例无关。4. 构造函数模式中,**浏览器默认把实例返回**,返回一个**对象数据类型**的值。如果自己在构造函数中写return。return 基本数据类型的值,则当前实例不变。若return 引用数据类型,则当前实例为该引用数据类型。复制代码
function Fn(){ this.x = 100; return [1,2,3]}var f1 = new Fn;console.log(f1); // [1, 2, 3]复制代码
- 原型链模式:在构造函数基础上,解决属性共有问题。
- var n1 = new Number和var n2 = 1有什么不同?var a1 = new Array和var a2 = []有什么不同?
answer:
new的形式是实例创建方式,n=1是对象字面量方式。前者是标准创建实例的方式。第二种是js弱类型语言独有的创建实例的方式。
针对引用数据类型:对象字面量,和类实例方式创建没有不同。 针对基本数据类型:两者不同。
var n1 = new Number(1);var n2 = 1;typeof(n1) // objecttypeof(n2) //numbern1 instanceOf Number //truen2 instanceOf number // false复制代码
- 解释一下js的原型链
答:
* 每个函数数据类型,都自带一个prototype属性,属性值为对象数据类型* prototype在浏览器环境下,拥有一个constructor属性,值为当前函数本身* 每个对象数据类型(普通对象,实例,prototype),也天生自带一个属性__proto__。指向`当前实例所属类的原型(prototype)`复制代码