阅读 78

前端学习笔记--原型和原型链

一、 全局对象

ECMAScript把全局对象称为global,但浏览器中将window作为全局对象,window的属性就是全局变量。

全局变量分两种,一种是ECMAScript标准规定的:

- global.parseInt
- global.parseFloat
- global.Number
- global.String
 -global.Boolean
- global.Object
- ...
复制代码

另一种是浏览器私有的:

- window.alert
- window.prompt
- window.comfirm
- window.console.log
- window.console.dir
- window.document
- window.document.createElement
- window.document.getElementById
- ...
复制代码

这里主要介绍 ECMAScript 标准中的全局变量

二、 全局函数

JS 中常见的全局函数有NumberStringBooleanObject等(实际是window.Number,在使用全局属性时,前面的windowglobal可以省略)

声明一个对象又两种方法,以Number为例:

var n = 1
var n = new Number(1)

在使用 var n = new Number() 声明一个Number对象时,n会具有一些属性和方法,如

var n1 = new Number(1)      //声明Number对象n1
n1.toString()               //'1'
n1.valueOf()                //1
复制代码

需要注意的是,在JS中,即使只是声明了一个number类型的量,也可以直接使用Number对象的方法。

var n2 = 1
n2.toString()               //'1'
n2.valueOf()                //1
复制代码

实际上,在对基本类型类型 n2 使用 toString 方法时,JS引擎会生成一个临时的 Number 对象 temp 在调用 n2.toString() 时,实际上是在调用 temp.toString() ,并将 temp.toString() 的返回值作为 n2.toString() 的返回值。

n2.toString()
/*实际运行的情况是
var temp = new Number(n2)
n2.toString() = temp.toString()    //'1'
*/
复制代码

需要注意的是,在上述过程执行完毕以后,temp 会被回收

var n = 1
n.xxx = 3
n.xxx  //undefined
复制代码

同样的,Number、String、Boolean等全局函数也可以这样声明

var s1 = 'Hello'
var s2 = 'World'

s1.concat(s2)       //'HelloWorld'
s1.charAt(4)        //o(获取s1的第4+1个字符)
s2.charCodeAt(3)    //108(获取s2的第3+1个字符的Unicode编码)
s1.slice(0, 2)      //He
s2.slice(2, 5)      //rld
s1.replacae('e', 'o')       //hollo(得到一个新字符串,但s1还是hello)
'  username  '.trim()       //username
复制代码
var f = false
var f2 = new Boolean(false)

if(f){console.log(1)}
if(f2){console.log(2)}      //2
复制代码
var o1 = {}
var o2 = new Object()
/*****
o1和o2没区别但是
o1 === o2       //false
*****/
复制代码

三、 原型与原型链

声明一个全局函数时会创建一个相应的对象实例,每个对象都有相应的属性和方法,但有一些属性和方法是所有对象都有的,即公有属性。如果每创建一个对象,都把这些共有的方法都创建一遍,就会造成内存浪费。

从上面打出来的结果可以看到:

  1. n1有一个 __proto__ 属性(基本类型 Number 的公有属性)
  2. n1.__proto__ 有很多属性,包括 toFixed、toExponential
  3. n1.__proto__ 中还有一个 __proto__ 属性,包括 valueOf、toString、constructor 等与 object.__proto__ 相同,这是因为 object.__proto__ 就是所有对象的公有属性。
  4. obj.__proto__ 实际上有一个叫做 __proto__ 的属性(console.log 没有显示),值为 null

当我们读取某个属性时,JS引擎先在自身属性中查找,找到返回,如果没有,再在__proto__中积雪查找,直到查找到或者__proto__null,整个过程中__proto__是一层嵌套一层,呈一种链式结构,称为原型链。

在JS中,每个函数都有一个特殊的属性叫作原型(prototype),指向每类函数的公有属性,保证了共有属性的存在性。因为JS中没有被引用的对象,会被当做垃圾回收掉,所以还需要有一个变量去引用它,才能保证随时可以调用这些共有属性。同时也解决了内存浪费的问题。

prototype__proto__的关系是:

var 对象 = new 函数()
对象.__proto__ === 对象的构造函数.prototype
复制代码

所以

var number = new Number()
number.__proto__ === Number.prototype

var object = new Object()
object.__proto__ === Object.prototype

var function = new Function()
function.__proto__ === Function.prototype
复制代码

所有函数都是由 Function 构造出来的(包括 Function 类型),所以

Number.__proto__ === Function.prototype  //ture
Object.__proto__ === Function.prototype  //ture
Function.__proto__ === Function.prototye  //ture 
复制代码
文章分类
前端
文章标签