js变量

总结js的变量这块的内容,从浅入深理解和正确使用JS的变量

目录

一、变量的命名规则

二、声明变量的方法

三、变量的提升

四、变量的作用域

五、变量的数据类型


题一:

        console.log('one',a);
        var a = 1;
        function a() {
            console.log('two',2)
        }
        console.log('three',a);
        var a = 3;
        function a() {
            console.log('four',a);
        }
        console.log('five',a);
        a();

执行结果:

编译结果:

        var a;
        var a;
        function a(){
            console.log('two',2)
        };
        function a() {
            console.log('four',a);
        };
        console.log('one',a);
        a = 1;
        console.log('three',a);
        a = 3;
        console.log('five',a);
        a();

js会经过编译之后才会执行。执行阶段是从上到下执行。这就是变量提升

题二

        console.log('one',a());
        var a = 1;
        function a() {
            console.log('two',2)
        }
        console.log('three',a);
        var a = 3;
        function a() {
            console.log('four',a);
        }
        console.log('five',a);
        a();

结果:

 

编译结果:

        var a;
        var a;
        function a(){
            console.log('two',2)
        };
        function a() {
            console.log('four',a);
        };
        console.log('one',a());  //注意 这里console出去的是a函数执行的结果 因为a函数没有return返回 所有是undefined
        a = 1;
        console.log('three',a);
        a = 3;
        console.log('five',a);
        a();

 

题三:

        console.log(a);
        a = 1;

一、变量的命名规则

变量名的组成规则:

  1. 区分大小写。允许包含字母、数字、$、_ 但是第一个字符不允许是数字,不能出现空格或者.等标点符号

变量名的命名规范:

  1. 命名长度尽量要短,抓住重点。要提现出变量名中值得体现的类型
  2. 见名知义
  3. 禁止使用关键字

变量名的书写规范:

  1. 驼峰式:大驼峰每个单词首字母大写
  2. 小驼峰:第一个单词首字母小写,其他单词首字母大写
  3. 未知名字:全部使用小写,单词与单词用下划线链接
  4. 匈牙利命名法:类型+对象描述 Int整型(i)Float浮点(f)boolean布尔(b)string字符串(s)array数组(a)object对象(o)function函数(fn)Regular Expression正则(re)

二、声明变量的方法

 声明方法:var let const class import function 

隐式声明

  1. 不使用任何关键字来声明变量。变量会默认为全局变量,挂载在window下

var声明变量

  1. 声明变量的时候存在声明提升
  2. 声明可以重复被使用
  3. 变量可以重复被赋值
  4. 声明变量时,在代码块内可以修改代码块外声明的变量
  5. var声明的变量全局内有效(函数外使用)
  6. 不要把var  放在代码块中
  7. 不要把var放在循环体中
  8. 每个函数都使用单一的var语句

let声明变量

  1. 声明一个只有块级作用域的变量
  2. 不能与var操作同名
  3. let不允许在相同作用域内声明同一个变量
  4. for循环内适合使用let
  5. 作用域范围块级的
  6. 声明的变量只在其代码块内生效
  7. let不会发生变量提升
  8. 在代码块中声明变量不受该代码块之外的干扰,也不会影响代码块之外的同名变量
  9. 全局的let定义的变量不会被当做window属性

const声明变量

  1. 一个常量不能和它所在的作用域内的其他变量拥有相同的名称
  2. 不可重复声明
  3. 声明的是常量,一旦声明常量的值不能改变
  4. 只在声明的块级作用域内有效
  5. 声明的常量不会受到外层代码块的干扰,同样也不会感染外部变量和常量
  6. 一旦声明变量,必须立刻初始化,不能以后赋值
  7. 指向的是常量所在的地址

function声明函数

  1. 函数的提升优先于变量提升
  2. 对于var声明的变量如果未赋值,则function定义的重名变量会覆盖掉var的声明;而当var声明的变量已被赋值,则function定义的重名变量无效。

class声明类

关键字:class  extends super constructor static

1.什么是class?Class 是ES6的语法。实际是对象继承的的语法糖
class SuperType{
    constructor(name){
        this.name = name;
    }
    SayName(){
        console.log(this.name);
    }
}
class可以看成构造函数的另外一种写法  constructor 就是构造方法  this关键字代表实例对象 SayName代表函数内部的方法
function SuperType(name) {
    this.name = name;
}
SuperType.prototype = {
    SayName:function () {
        console.log(this.name);
    },
}
调用方法都一样 使用new 操作符 class 会直接调用 constructor方法 返回对象的实例  直接调用class的方法会报错  除非显式的定义在this对象上。否则其他都在原型上 class 定义不存在变量提升  先使用在定义是错误的

 

2.extends 继承
通过extends 关键字实现继承,这比ES5通过修改原型链实现继承要清晰和方便
class SubType extends SuperType{
    constructor(name,age){
        super(name);
        this.age = age;
    }
}
super 表示 父类的构造函数 用来新建父类的this对象 即可以当函数使用 也可以当做对象使用 super作为函数调用时,代表父类的构造函数 super() 只能用在子类的构造函数中 子类中super.SayName() super指向父类的prototype
3.static 静态方法 所有在类中定义的方法都会实例继承。如果在方法前面 + static关键字 表示该方法不好被实例继承。直接通过类来调用 称为静态方法  父类的静态方法可以被子类继承
class SubType extends SuperType{
    constructor(name,age){
        super(name);
        this.age = age;
    }
    static SayAge (){
        console.log(this.age);
    }
}
SubType.SayAge();
var a = new SubType();
a.SayAge();

 

4.Mixin模式 将多个类的接口混入 mix in 另一个类中

function mix(...mixins) {
    class Mix {}

    for (let mixin of mixins) {
        copyProperties(Mix, mixin);
        copyProperties(Mix.prototype, mixin.prototype);
    }

    return Mix;
}

function copyProperties(target, source) {
    for (let key of Reflect.ownKeys(source)) {
        if ( key !== "constructor"
            && key !== "prototype"
            && key !== "name"
        ) {
            let desc = Object.getOwnPropertyDescriptor(source, key);
            Object.defineProperty(target, key, desc);
        }
    }
}
//使用
class DistributedEdit extends mix(Loggable, Serializable) {
    // ...
}

 

import声明

用于导入另外一个模块的导出绑定

全部语法:

import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";

 具体分析:

1.

import '/modules/my-module.js';

不导入任何模块,仅仅执行对应文件中的全局代码。一般用来指定某些补丁包

2.

import myDefault from "my-module";

直接导入默认值

3.

import * as myModule from '/modules/my-module.js';

这将myModule插入当前作用域,其中包含来自位于/modules/my-module.js文件中导出的所有模块

例如my-modules中有个doScroll方法,调用的时候需要 myModule.doScroll() 来执行

4.

import {myExport} from '/modules/my-module.js';

单个导入,将my-module.js模块下名为myExport的文件导出,并且将myExport插入当前作用域

5.

import {foo, bar} from '/modules/my-module.js';

同时导出多个对象或者值 foo和bar 其中foo 和bar 要在export中完全匹配

6.

import {reallyReallyLongModuleExportName as shortName}  from '/modules/my-module.js';

导入时候重命名将reallyReallyLongModuleExportName导出并且重命名为shortName

7.

import {
  reallyReallyLongModuleMemberName as shortName, 
  anotherLongModuleName as short
} from "my-module";

使用别名的多个模块导出

8.

import myDefault, * as myModule from "my-module";

将模块myDefault导出并且赋值给myModule变量

export全部语法:

export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName() {...}
export class ClassName {...}

export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };

export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;

注意:命名导出(export)对导出多个值很有用。在导入(import)期间,必须使用相应对象的相同名称。可以使用任何名称导入默认导出

export default k = 12; // in file test.js

import m from './test' // note that we got the freedom to use import m instead of import k, because k was default export

console.log(m);        // will log 12

多个export导出在不同环境展示不同的问题 babel 版本问题

 

三、变量的提升

变量的生命周期:

  1. 变量声明
  2. 变量初始化
  3. 变量使用
  4. 变量销毁

注意:const的声明和初始化是一起的。当变量被保留引用的时候,不会被销毁。

变量提升的原因:

  1. js代码运行之前有编译阶段,编译是从上到下执行的。编译完毕,才是执行阶段。js在代码编译阶段的主要工作:将变量和作用域关联。把函数和变量的声明提升至顶端。变量提升只提升声明。不提升赋值操作

变量的先提升,函数后提升。函数会覆盖同名的变量。函数的优先级较高

四、变量的作用域

全局作用域

  1. 在函数体外定义的变量
  2. 在函数体内隐式声明的变量
  3. window.标识符声明
  4. 可以在任何位置调用

局部作用域

  1. 函数内部使用var声明
  2. 函数的参数
  3. 只能在函数内部调用

块级作用域

  1. 块级作用域if
  2. 块级作用域for

优先级

  1. 局部变量高于同名的全局变量
  2. 参数变量高于同名的全局变量
  3. 局部变量高于同名的参数变量

特性

  1. 局部变量是调用对象的属性
  2. 全局变量是全局对象的属性
  3. 内层函数可以访问外层函数的局部变量
  4. 外层函数不能访问内层函数的局部变量

五、变量的数据类型

基本类型

  1. 占用空间固定保存在栈中
  2. 保存于与复制是值的本身
  3. 使用typeof检测数据类型
  4. 数据类型:string null boolean Number undefined

引用数据类型

  1. 占用空间不固定,保存在堆中
  2. 保存与复制是指向对象的一个指针
  3. 使用instanceof检测数据类型
  4. 使用new 方法构造出的对象是引用类型

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值