两张图解释原型与原型链

在这里插入图片描述
上面这张图出自 冴羽的博客,这张图已经能很好地解释原型与原型链了,其涉及到的属性如下:

  • prototype: 每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,如果使用这个函数生成了实例,那么称这个对象为所有实例的原型。
  • __proto__: 每个对象都拥有__proto__属性,该属性用于实现原型链,当访问一个对象的属性时,如果该对象内部不存在这个属性,就通过原型链找直到找到或者到终点 null。
  • constructor:每个原型都有一个 constructor 属性指向关联的构造函数

我们可以用下面这段代码验证一下:

function Person () {

}

let person = new Person()
console.log(person.__proto__ === Person.prototype) // true
console.log(Person.prototype.constructor === Person) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true

下面这张图咱自己画的,主要是分析下 Object 与 Function 的原型问题:
所有的对象都是由 Object() 构造函数构造的,所有的函数声明 / 函数表达式都是 Function() 构造函数的实例,而 Object() 构造函数本身又是 Function() 构造函数的实例,其原型关系如下:
在这里插入图片描述
需要注意的是 Function() 的__proto__属性直接指向的是其原型对象。
我们可以用下面的代码来验证这张图:在 node 环境及浏览器环境下都是一样的结果

console.log(Object.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__ === null) // true
<< ### 闭包(Closure) **定义:** 闭包是指函数能够记住并访问它的词法作用域,即使这个函数在其词法作用域之外执行。 **举例说明:** ```javascript function createCounter() { let count = 0; return function() { count++; console.log(count); } } const counter = createCounter(); counter(); // 输出1 counter(); // 输出2 ``` 在这个例子中,`createCounter` 函数返回了一个匿名函数,并且该匿名函数记住了 `count` 变量。每次调用 `counter()` 都会改变 `count` 的值并且输出最新的结果。 #### 解释: - **闭包的好处:** 它可以帮助我们创建私有变量, 实现数据隐藏等. - **注意点:** 如果不正确地使用闭包可能导致内存泄漏. --- ### 作用域(Scope) **定义:** 作用域指的是程序源代码中定义变量的区域,在 JavaScript 中主要有两种类型的作用域 - 全局作用域局部(块级)作用域。 **全局作用域:** 当一个变量被声明为 global 或者是在最外层环境中时就属于全局作用域。 例如: ```javascript var globalVar = "I am a global variable"; console.log(globalVar); // 即使在其他地方也可以读取到globalVar ``` **局部作用域 (包括函数作用域 和 块级作用域):** 如果将变量放在一对花括号 `{}` 内,则此部分形成了一个新的作用域环境,即局部作用域或称为块级作用域;而由函数形成的叫作函数作用域。 ```javascript if(true){ var blockScopedVariable = 'block scoped'; } console.log(blockScopedVariable); // undefined in strict mode function myFunc(){ const funcScopedVariable = 'func scoped'; } myFunc(); console.log(funcScopedVariable); // ReferenceError ``` > 注意:ES6 引入了新的关键字如 `let`, `const` 来替代传统的 `var`. 使用这些新关键字可以更好地控制作用域范围,避免了一些传统意义上的“变量提升”等问题的发生。 --- ### 原型链(Prototype Chain) **定义:** 每个对象都有自己的属性和方法,但有时候我们也希望继承自另一个已经存在的对象所具有的某些特征及行为模式。此时就可以利用原型的概念来进行扩展。每个实例对象都有一条指向其构造器(constructor)内部 `prototype` 属性的指针(`__proto__`) ,这就是所谓的"原型链接". 当查找某个成员不存在于当前对象自身的时候就会顺着这条链条向上寻找直至找到根节点 Object.prototype。 **示例:** ```javascript function Person(name) { this.name = name; } Person.prototype.sayHello = function () { console.log("Hello," + this.name); }; let p1 = new Person('Alice'); p1.sayHello(); console.dir(Person.prototype === p1.__proto__); // true ``` 这里展示了如何给 `Person` 类添加公共的方法 `sayHello` ,所有从 `Person` 继承来的子类都可以共享这段逻辑而不必重复编写同样的代码片段。 #### 解释: - 在 JavaScript 中一切皆为对象,因此它们都是基于原形的方式构建出来的; - 每个函数默认都有一个 prototype 属性用于指定它自己作为其它对象构造器时应附加哪些额外信息上去; - 对象之间通过 __proto__ 进行关联形成了一张巨大的网状结构谱也就是我们所说的 “原型链”。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值