JS 的其他重要概念!
万物皆对象?
1,说法原因
历史因素:
JS 的诞生是参考了 js 的;在 Java 中一切皆对象,但基本类型却不是对象,为了解决这个问题,Java 让每个基本类型都对应了一个包装器类型。包装器类型将基本类型包装起来,添加了属性和方法,包装器类型即为对象,所以可以这么说 Java 中的一切都可以充当对象,不会说的那么绝对。
我们可以把对象看作是一个属性的集合,每一个属性都有一个名称和值(键值对)。
在 JS 这门面向对象编程的语言,几乎所有的东西都可以是对象;但除开直接书写的原始数据类型,其它东西都是对象;基本数据也可以通过内置构造函数书写,如利用 toString(),改变数据类型为 string,这样它就是一个对象了;
所以在 js 中并非所有内容都是对象,而是所有内容都可以充当对象;
2,原始类型和对象
在 JS 中值可以分为两大类,原始类型和对象,基本上就区分了对象和其它;
六类原始数据类型:
Boolean,null,undefined,number,string,symbol(ES6);
对象:
1,原始值的包装类型,通过系统包装构建出来的原型类型对象:如 Boolean,Number,String;
2,函数和数据是对象的一等公民,是对象里使用和功能最强大的两个;
3,通过构造函数 new 出来的值,都是对象;
4,正则表达式也是对象;/\s*/ 类同与 new RegExp(“\s”)
不同点:
1,是否可变:原始类型没有附加方法,所有你永远看不到 undefined.toString(),因此原始类型是不可变的;对象在默认情况下是可变的,可以添加方法;
2,储存方式:原始类型按值存储,对象通过引用存储;存储地址也不同,原始类型直接存在栈中,对象存放在堆中;
数据的储存
在 jave 中原始数据类型一般储存在栈里,对象一般储存在堆里;
JS 内存存放机制:
1)基本数据类型:string number boolean undefined null
如果变量后面的值是基本数据,就直接存在栈内存。栈里面要求变量不能重名,如果重名就会覆盖前者
2)引用数据类型:object array function
如果变量后面是引用数据类型,将后面的代码块存在堆内存中,然后将堆内存中的内存地址赋值给前面的变量
js 内存中,保存变量根本不是用栈和堆的。存储任何变量和数据,用的都是对象。而 js 中对象底层其实都是一种叫关联数组的数据结构。对象或关联数组的存储结构内部都是由多组”属性名:属性值”这种名值对儿组成的。js 中,连作用域也都是一个个的对象。其中,担当全局作用域的对象其实名为 window。window 对象在你刚一打开网页,就自动创建了。
this 关键字
this 的本质是在对象创建时,指向对象的一个地址;
有关 this 的方法,函数(对象)的方法;
bind(),改变对象的 this 指向,无参;
call(),改变对象的 this 指向,自动调用,多个参数;
apply();改变对象的 this 指向,自动调用,参数为数组;
深拷贝和浅拷贝
都创建了一个新对象;
let a = {};
let b = a; //使用的是浅拷贝 相当于把对象地址给b
a.name = 10; //a的地址和b的地址指向同一个内容 a里面添加一个name b也添加
console.log(b.name); //10
1,深拷贝:创建一个新对象,拷贝所拷贝对象的所有内容(跟原本的内容无关系也不影响)
深拷贝是把储存在堆里的数据全部拷贝了一份新的出来,不引用地址;
实现方法:
a,递归遍历到没有对象后结束;
b,JSON.parse(常用)
let a = [1, 2, 3, { name: 1, age: 2, list: [1, 2] }];
let str = JSON.stringify(a);
let aCopy = JSON.parse(str);
console.log(a == aCopy); //false
2,浅拷贝:只拷贝第一层内容(对于里层的内拿到的都是地址)
浅拷贝在对储存在堆里的数据进行拷贝时,是引用复制了其地址,堆中的数据还是只有一份;
//浅拷贝
let arr = [];
for (let key in a) {
arr[key] = a[key];
}
console.log(arr[3] === a[3]); //true 拷贝的是对象的地址