在面向对象及函数编程语言中,不可变对象是一种对象。在被创造之后,它的状态就不可以被改变。状态可以被改变的对象,则被称为可变对象。
这里状态可以简单理解为对象的值。
在javascript中,原始值(undefined, null, 布尔值, 数字和字符串)这些都是不可变原始值。
理解:不可变说的是一旦这些基本类型值创建后会一直保存其内存地址,直到被浏览器的垃圾回收机制回收。而我们一直用的创建一个字符串变量,只是将这个变量指向了该字符串的内存地址,当改变该变量的值,也就是改变了该变量指向的字符串内存地址,而原来的字符串还在内存中存在。
js对象的属性值发生改变,会创建一个新的属性值,然后改变的是该属性指向的内存地址。对象本身的内存地址是没有改变的。这样对象的内存地址没有变化。
原始值
:任何方法都无法更改一个原始值。
示例:
let s = 'hello'; // 这里申请内存,并保存数据hello,并把内存地址赋给
s.toUpperCase(); // 生成一个新的数据HELLO,并申请内存保存之
s = s.toUpperCase(); // 把新的内存地址赋给s,此时s的值就是HELLO了。原来的'hello'会被回收。
一、js数据
1.typeof
-
typeof
返回一个字符串,指示未经计算操作数的类型。 -
typeof
能区分值类型的详细类型,但对于引用类型就不行了。 -
typeof null
返回object是历史遗留问题,自从js出现就是这样的。 -
typeof
通常只返回6种数据类型:number
,string
,boolean
,undefined
,object
,function
,symbol
2.instanceof
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数
的 prototype 属性。
语法:
// obj是使用构造函数构造的变量,Object是构造函数的名称
obj instanceof Object
3.字面量创建变量和new 构造函数创建变量
什么是字面量?
两者区别:
- 字面量创建对象
let obj = { id: 1, };
let str = 'abc';
let num = 123;
上面创建变量时,不会调用构造函数。是一个原始类型(基本类型)的值。
使用new
后,会将原始数据类型转为对象。
- 构造函数创建变量
let obj = new Object({ id:1 });
let str = new String('abc');
let num = new Number(123);
new
方式创建变量的本质是方法调用,会遍历__proto__
中的方法和属性,找到该构造函数的方法,然乎生产方法调用必须的堆栈信息,方法调用结束后,还要释放堆栈,性能不如字面量方式。
问题:
- 字面量方式创建的变量,为什么有构造函数函数创建的变量的方法和属性?
可以参考这个问题
涉及到包装类型
。
发现一个有趣的:
4.原型
-
原型对象
:这个原型对象包含所有实例共享
的属性和方法。其实最初指的是函数的prototype
。
当使用构造函数实例化时,实例化后的是对象,会将实例化对象的
__proto__
指向构造函数的prototype
。任意一个
函数
(包括构造函数)都有一个prototype
属性。函数也是对象。所有
对象
都有__proto__
属性。构造函数实例化后的是一个对象。
自己理解示例:
let str = new String('abc')
一、str.__proto__
1. str.__proto__
是对象,没有prototype
。
2. str.__proto__
指向(或继承)构造函数String
的String.prototype
。
二、String.prototype
1. String.prototype
包含构造函数String
自定义的属性和方法。String.prototype
还包含构造器constructor
和__proto__
。
1.1 String.protype.constructor
指向本身的函数String
1.2 String.prototype.__proto__
:因为String.protype.
是对象,下面无构造函数了,所以String.prototype.__proto__
指向的是对象的原型prototype
。对象指的不是Object
,Object
是函数。
新建函数时,函数的
prototype
下的__proto__
指向的是对象的原型prototype
。
新建的对象没有prototype
属性。
三、String.__proto__
1. String.__proto__
指向的是构造函数String
的构造函数Function
的prototype
,即Function.prototype
。
四、Function.prototype
-
Function.protype.constructor
指向本身的函数Function
-
Function.prototype.__proto__
:因为Function.protype.
是对象,下面无构造函数了,所以Function.prototype.__proto__
指向的是对象的原型prototype
。
五、Function.__proto__
1. Function.__proto__
指向Function.prototype
。即 Function.__proto__
和Function.prototype
相等。所以Function.__proto__
也指向的是对象的原型prototype
。
5.原型链
- 由于
__proto__
是任何对象都有的属性,所以最终会形成一条__proto__
连起来的链条,递归访问__proto__
必须最终到头,并且值是null。 - 当js引擎查找对象的属性时,先查找对象本身是否存在该属性,如果不存在,会在原型链上找,但不会查找自身的
prototype
。
- 给原型
prototype
添加方法和属性