const
之前用var声明变量,变量想怎么改就怎么改,这里const关键字也是声明变量的,不过声明的是常量,常量就是固定的一个值,不能改变
其他功能更let 差不多
不存在变量提升,但必须提前声明,和let一样
if(true){
alert(age); //报错 使用时 未声明
const age=20;
}
不可重复声明同一个变量
var age=20;
const age=20;//报错 因为变量age已经存在
声明后要赋值,没有赋值要报错
const age=20;
const name;//报错。因为没有赋值;
这个时候,我们先引入一个概念:在赋值过程中,我们可以分为传值赋值和传址赋值。这里我们用到了传址赋值,什么叫传址赋值?
传址:在赋值过程中,变量实际上存储的是数据的地址(对数据的引用),而不是原始数据或者数据的拷贝
var student1 = {"name":"张三"};
var student2 = student1;
student2.name = "李四";
console.log(student1);
//结果:输出 {name: "李四"}
console.log(student2);
//结果:输出 {name: "李四"}
为什么student2的name改成了“李四”,student1的那么也变成了“李四”呢?这就是传址赋值!
如果这样写的话就会报错:
const Person = {"name":"张三"};
Person.age = 20;
Person = {};
//错误,企图给常量Person赋新值(新地址)
js 引用赋值和传值赋值
number,string类型都是基本类型,而基本类型存放在栈区,访问时按值访问,赋值是按照普通方式赋值;
对象和数组是通过引用来赋值的,所以改变a的同时b也会跟着改变。
如果你对栈和堆不太理解以下引用百度一张图可以非常清晰:
解构
如果是数组的话key要对应上
let [a1, a2] = [1, 2, 3]; //数组的key要对应上
console.log(a1,a2); // 1,2
// =可以赋默认值 :用来更改名字的,obj可以不对应key,name对应上就可以l
let arr = [{name:'zfpx',age:9},'回龙观',[1,2,3]];
let [{age,address="东大街"},b] = arr;
console.log(b,age,address); // 回龙观 9 东大街
展开运算符
// 展开运算符 可以合并对象和数组
let school = {name:'zfpx',age:9};
let me = {name:'jw',address:'回龙观'}
let obj = {...school,...me};
console.log(obj);
类 Class
先说说 以前就是构造函数
function Parent(){
this.name = '';
}
Parent.prototype.smoking = function(){
console.log('吸烟')
}
function Child(){
}
Child.prototype = new Parent();
let child = new Child;
console.log(child.name);
当我们创建一个函数,系统就会为这个函数自动分配一个prototype指针,指向它的原型对象。并且可以发现,这个原型对象包含两个部分(constructor 和 proto)其中constructor指向函数自身。
当然,当我们将该函数作为模版创建实例(new方法)的时候,我们发现创建出的实例是一个与构造函数同名的object,这个object是独立的,他只包含了一个proto指针(实例没有prototype,强行访问则会输出undefined),这个指针指向上面提到的构造函数的prototype原型对象。
方便理解特意画了一张图
所以当Child.prototype = new Parent();的时候,child继承parent 的公有和私有方法和属性,但是这样做有个问题,就是child的构造函数指向的是Parent。