JS 的三座大山
- this
- 原型
- AJAX
- JS 要有很多东西,这些东西都挂在 window 上,浏览器就提供了 window
对象是 { } 的完整写法 Array 是 [ ] 的完整写法 Function 是小写 function 的完整写法
- 都挂在 window 上是为了方便在任何地方直接用
内存图
- 指向和引用的意思是保存了它的地址
关于 window
- window 变量和 window 对象是两个东西
- window 变量是一个容器,存放 window 对象的地址
- window 对象是
Heap
里的一坨数据 - 例:
var x = window
,那么这个x
就指向了 window 对象,window 变量可以消失了
同理:
console
和console
对象不是同一个东西Object
和Object
函数对象不是同一个东西- 前者是内存地址,后者是一坨数据
原型链
目前只关心小写对象的隐藏属性,不关心大写对象的隐藏属性,避免绕晕。
下列的代码为什么不报错 ? 为什么可以运行 ?
var obj = {}
obj.toString()
图解1:
obj
有一个隐藏属性- 隐藏属性存储了
Object.prototype
对象的地址 obj.toString()
发现obj
上没有toString
- 就去隐藏属性对应的对象里找
- 于是就找到了
Object.prototype.toString
obj 和obj2 有什么联系?
var obj = {}
obj.toString()
var obj2 = {}
obj2.toString()
相同点:
- 都可以调用
**.toString()**
不同点:
- 地址不同
**obj !== obj2**
- 可以拥有不同的属性
问:如果 obj
改变了 toString
,那新创建的 obj2
的 toString
是否会被改变?
答:不会
- 一层是可以篡改的,两层是没有简单的办法篡改的,除非通过图示中的 ‘fuke’(也就是
__proto__
来篡改)。
1. 什么是原型?
**XXX.prototype**
储存了 **XXX**
对象的共同属性,这就是原型。
2. 什么情况下有 prototype 属性?
答:如果第一个字母是大写就有 prototyp
属性。例如:Object、Array等。
3. 原型的作用:
- 原型可以无需重复声明共有属性
-
4. 隐藏属性叫什么?
-
5. 隐藏属性的作用:
每个对象都有一个隐藏属性,指向原型(对象)
如果没有这个隐藏属性,那么
obj
都不知道自己的共有属性在哪6.
Object
作为对象是否具有隐藏属性?Object
也有隐藏属性,它的隐藏属性指向哪里涉及到一个 JS 的哲学问题,暂不讨论- 只需知道如果一个对象的首字母是大写的,它就会拥有一个
prototype
属性,然后就不用关心它的隐藏属性 - 只有对象首字母为小写的时候再关心它的隐藏属性
需要先把小写的隐藏属性搞清楚,再去理解大写的,不然容易绕晕。
**Object**
和**object**
的区别是什么?Object 是一个全局函数,可以用来生成对象,
var obj = new Object()
,可以简写成var obj = {};
而 object 什么也不是,除非我声明一个
var object
7.
**prototype**
和**__proto__**
区别是什么?都存着原型的地址
- 只不过
**prototype**
都挂在函数上 **__proto__**
挂在每个新生成的对象上
问:下面的代码为什么不报错?为什么可以运行?
var arr = [1,2,3]
arr.join('-')
图解:
arr
有一个隐藏属性- 隐藏属性储存了
Array.prototype
对象的地址 arr.join()
发现arr
上没有join
,就去隐藏属性对应的对象里找,于是找到了Array.prototype.join
8. 在不同的数组里的共有属性是否能篡改?
在不同的数组里去篡改共有属性是无法篡改的,因为改的时候读不到共有属性,只有在读的时候才能读到共有属性。
9. 关于原型(共有属性),正确的有
- Object.prototype 保存了一个对象的地址,这个对象包含了所有普通对象的共有属性,叫做对象的原型
- Array.prototype 保存了一个对象的地址,这个对象包含了是所有数组的共有属性,叫做数组的原型
- Function.prototype 保存了一个对象的地址,这个对象包含了是所有函数的共有属性,叫做函数的原型
- 每个对象都有一个隐藏属性,用来保存其原型的地址,这个隐藏属性的名字叫做 proto
原型和共有属性的区别?
- 原型是对象
- 共有属性是属性
- 原型包含了所有共有属性(共有属性依附在原型这个对象上)
| 红圈为原型
蓝线画的是一个个共有属性 || | —- | —- |
原型
每个对象都有原型
- 原型里存着对象的共有属性
- 比如 obj 的原型就是一个对象
obj.__proto__
存着这个对象的地址这个对象里有
toString / constructor / valueOf
等属性对象的原型也是对象
所以对象的原型也有原型
obj = {}
的原型即为所有对象的原型- 这个原型包含所有对象的共有属性,是对象的根
- 这个原型也有原型,是 null
JS 重要且唯一的公式:原型公式
对象.proto === 其构造函数.prototype
Object.prototype 与原型的关系?
- Object.prototype 存了原型的地址
- 结论:
- 你是谁构造的,你的原型就是谁的 prototype 属性对应的对象
参考资料:《proto和prototype存在的意义是什么》方方
问:
let square = new Square(5)
square 的原型(square.__proto__ 的值)是什么?
Square.prototype
Object.prototype
是哪个函数构造出来的?- 不知道,它没有父母
- Object.prototype 的原型是什么?
- 根对象没有原型
- Object.prototype.proto?
null