We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
这图很经典,希望先试着解读每个箭头的含义
对象都是通过函数创建的,函数是对象(剪不断,理还乱,是离愁,别是一番滋味在心头)
Prototype
每个函数都有这属性,有且仅有函数才拥有该属性 但有个例外:
// 用这个方法创建的函数是不具备prototype属性的 let fun = Function.prototype.bind()
Prototype属性里面默认有一个属性constructor,对应着构造函数
constructor
constructor是一个公有的而且不可枚举的属性,一旦改写了函数的Prototype,新对象就没有这个属性了
__proto__
每个对象都有一个隐藏属性__proto__,这个属性引用了创建这个对象的构造函数的原型 fn.__proto__ === Fn.prototype
fn.__proto__ === Fn.prototype
__proto__ 将对象和原型连接起来组成了原型链
有三个要注意的地方
Object.prototype.__proto__ === null
对象的原型的__proto__属性是null
Object.__proto__ === Function.prototype
既然对象是函数创建的,那么对象的__proto__要指向创建它的构造函数的原型
Function
Function.__proto__ === Function.prototype
函数也是被Function创建的,那么函数的__proto__也应该指向Function的原型,这是一个环形结构,函数的prototype和__proto__属性指向同一个对象
prototype
Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建
Function.prototype
Object.prototype
new
除了以上Function.prototype 和 Object.prototype两个特殊对象,其他对象都是通过构造器 new 出来的
先看看new的实现过程
function create() { // 创建一个新的对象 let obj = new Object(); // 取出第一个参数,该参数就是我们将会传入的构造函数 // arguments会被shift去除第一个参数 let Constructor = [].shift.call(arguments); // 将obj的原型指向构造函数,此时obj可以访问构造函数原型中的属性 obj.__proto__ = Constructor.prototype; // 改变构造函数的this的指向,使其指向obj // 此时obj也可以访问构造函数中的属性了 let result = Constructor.apply(obj, arguments); // 确保 new 出来的是个对象 // 返回的值是什么就return什么出来 return typeof result === 'object' ? result : obj }
所以平时更推荐使用字面量的方式创建对象,因为使用new Object()需要通过作用域链往上层层寻找Object
new Object()
Object
因为存在我们创建了一个同名的构造函数Object()的可能,当调用Object()的时候,解析器需要顺着作用域链从当前作用域开始查找,如果在当前作用域找到了名为Object()的函数就执行,如果没找到,就继续顺着作用域链往上照,直到找到全局Object()构造函数为止
Object()
全局Object()构造函数
上面说__proto__ 将对象和原型连接起来组成了原型链
具体起来说就是:访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链
来看个例子
function Foo() {}; let f1 = new Foo(); f1.a = 1; Foo.prototype.a = 10; Foo.prototype.b = 20; // 打印自身属性和原型属性 for(const item in f1) { console.log(item) } // 打印自身属性 for (const item1 in f1) { if (f1.hasOwnProperty(item1)) { console.log(item1); } }
稍等一下,hasOwnProperty这个方法从哪找的? f1和Foo.prototype都没有啊
hasOwnProperty
f1
Foo.prototype
很好,它从Object.prototype继承而来的,由于__proto__的存在,可以查找下面这条链条 f1 => Foo.prototype => Object.prototype 最终找到了Object.prototype上定义的各种原生方法
那我们平时看见的call、apply,还有数组的一些方法呢? 它们分别在Function.prototype,Array.prototype上面,我们日常使用的原生方法都继承于这几个对象,可以尝试去浏览器控制台打印这两看看
call
apply
Array.prototype
console.dir(Function.prototype); console.dir(Array.prototype)
原型、原型链我说清楚了吗?
参考资料 深入理解javascript原型和闭包(1)——一切都是对象 - 王福朋 - 博客园 深度解析原型中的各个难点 · Issue #2 · KieSun/Blog · GitHub
The text was updated successfully, but these errors were encountered:
加个微信吧!
Sorry, something went wrong.
这句话读了两三遍,这样可能更好一点
构造函数的原型属性里面默认有一个constructor属性,指想构造函数
很好,它从Object.prototype继承而来的,由于__proto__的存在,可以查找下面这条链条 f1 => Foo.prototype => Object.prototype
这个应该是
很好,它从Object.prototype继承而来的,由于__proto__的存在,可以查找下面这条链条 f1 => Foo.__proto__=> Object.prototype
很好,它从Object.prototype继承而来的,由于__proto__的存在,可以查找下面这条链条 f1 => Foo.prototype => Object.prototype 这个应该是 很好,它从Object.prototype继承而来的,由于__proto__的存在,可以查找下面这条链条 f1 => Foo.__proto__=> Object.prototype
能加一下你微信吗?
No branches or pull requests
这图很经典,希望先试着解读每个箭头的含义
对象都是通过函数创建的,函数是对象(剪不断,理还乱,是离愁,别是一番滋味在心头)
一、
Prototype
每个函数都有这属性,有且仅有函数才拥有该属性
但有个例外:
Prototype
属性里面默认有一个属性constructor
,对应着构造函数constructor
是一个公有的而且不可枚举的属性,一旦改写了函数的Prototype
,新对象就没有这个属性了二、
__proto__
每个对象都有一个隐藏属性
__proto__
,这个属性引用了创建这个对象的构造函数的原型fn.__proto__ === Fn.prototype
__proto__
将对象和原型连接起来组成了原型链有三个要注意的地方
1、
Object.prototype.__proto__ === null
对象的原型的
__proto__
属性是null2、
Object.__proto__ === Function.prototype
既然对象是函数创建的,那么对象的
__proto__
要指向创建它的构造函数的原型3、
Function
的特殊性Function.__proto__ === Function.prototype
函数也是被
Function
创建的,那么函数的__proto__也应该指向Function
的原型,这是一个环形结构,函数的prototype
和__proto__
属性指向同一个对象Function.prototype
和Object.prototype
是两个特殊的对象,他们由引擎来创建三、
new
除了以上
Function.prototype
和Object.prototype
两个特殊对象,其他对象都是通过构造器 new 出来的先看看new的实现过程
所以平时更推荐使用字面量的方式创建对象,因为使用
new Object()
需要通过作用域链往上层层寻找Object
四、原型链
上面说
__proto__
将对象和原型连接起来组成了原型链具体起来说就是:访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着
__proto__
这条链向上找,这就是原型链来看个例子
稍等一下,
hasOwnProperty
这个方法从哪找的?f1
和Foo.prototype
都没有啊很好,它从
Object.prototype
继承而来的,由于__proto__
的存在,可以查找下面这条链条f1
=>Foo.prototype
=>Object.prototype
最终找到了
Object.prototype
上定义的各种原生方法那我们平时看见的
call
、apply
,还有数组的一些方法呢?它们分别在
Function.prototype
,Array.prototype
上面,我们日常使用的原生方法都继承于这几个对象,可以尝试去浏览器控制台打印这两看看原型、原型链我说清楚了吗?
参考资料
深入理解javascript原型和闭包(1)——一切都是对象 - 王福朋 - 博客园
深度解析原型中的各个难点 · Issue #2 · KieSun/Blog · GitHub
The text was updated successfully, but these errors were encountered: