【js重学系列】原型
初始
- JavaScript 中,万物皆对象!
- 但对象也是有区别的。分为普通对象和函数对象,像Object ,Function 是JS自带的函数对象
- 怎么区分?其实很简单,凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。
- Function Object 也都是通过 New Function()创建的。
构造函数
-
构造函数可用来创建特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。
-
function Person() { } var person = new Person(); person.name = 'Kevin'; console.log(person.name) // Kevin
-
按照国际惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。
-
要创建Person的新实例,必须使用new操作符。一般是经历以下四个步骤:
- 创建一个空对象(即{});
- 设置原型链(将实例对象的原型对象,指向构造函数的原型对象)
- 新创建的对象作为this的上下文 ,只改this指向并且把参数传递过去
- 如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象
原型
-
无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。普通对象没有 prototype,但有
__proto__
属性。 -
如上面例子,Person.prototype 指向了原型象,而 Person.prototype.constructor 又指回了Person。
-
而 person 只是一个对象实例。
-
而person可以访问保存在原型中的值,但却不能重写原型中的值。如果我们在 person 中添加一个属性,而该属性与实例原型中的一个属性同名,那个person中的属性会暂时屏蔽原型中的属性,删除后,还是读回原型中的属性
-
function Person() { } Person.prototype.name = 'Perty'; var person = new Person(); person.name = 'Kevin'; console.log(person.name) // Kevin delete person.name console.log(person.name) // Perty 解析器的操作是: “实例person有name属性吗?” “有” —— 于是就读取实例中的name属性,输出 Kevin 删除后,再运行时: “实例person有name属性吗?” “没有” “person的原型有name属性吗?” “有” —— 于是就读取原型中的name的属性,输出 Perty
-
①所有
引用类型
都有一个__proto__(隐式原型)
属性,属性值是一个普通的对象
②所有函数
都有一个prototype(原型)
属性,属性值是一个普通的对象
③所有引用类型的__proto__
属性指向
它构造函数的prototype
-
var a = [1,2,3]; a.__proto__ === Array.prototype; // true
原型链
-
在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做
__proto__
的内置属性,用于指向创建它的函数对象的原型对象 prototype。以上面的例子为例: -
console.log(person.__proto__ === Person.prototype) *// true*
-
同样的,Person.prototype 也同样有 proto 属性,它指向创建它的函数对象(Object)的prototype
-
console.log(Person.prototype.__proto__ === Object.prototype) *// true*
-
继续,Object.prototype对象也有__proto__属性,但它比较特殊,为nul
-
console.log(Object.prototype.__proto__) *// null*
-
我们把这个有
__proto__
串起来的直到Object.prototype.__proto__
为null的链叫做原型链。 -
person.__proto__ ==> Person.prototype.__proto__ ==> Object.prototype.__proto__ ==> null
-
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的
__proto__
隐式原型上查找,即它的构造函数的prototype
,如果还没有找到就会再在构造函数的prototype
的__proto__
中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链
。 -
function Parent(month){ this.month = month; } var child = new Parent('Ann'); console.log(child.month); // Ann console.log(child.father); // undefined
-
在child中查找某个属性时,会
执行下面步骤
: -
-
-
①一直往上层查找,直到到null还没有找到,则返回
undefined
②Object.prototype.__proto__ === null
③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象
链接:
https://blog.csdn.net/xiaoermingn/article/details/80745117
https://juejin.cn/post/6844903540943503367
https://www.jianshu.com/p/ddaa5179cda6
https://www.jianshu.com/p/dee9f8b14771