您的位置:首页 > Web前端 > JavaScript

js原型链、继承

2018-02-04 06:03 232 查看

Prototype(原型)

原型链原理

点击链接

含义:我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性

属性的作用

Prototype通过调用构造函数而创建那个对象实例的原型对象

当实例对象本身没有某个属性或方法的时候,会到构造函数的prototype属性指向的对象,去寻找该属性或方法;如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。

demo:

function Animal (name){
this.name = name;
}

Animal.prototype.color = 'white';

var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');

cat1.color // 'white'
cat2.color // 'white'


构造函数Animal的prototype对象,就是实例对象 cat1和cat2的原型对象,在原型对象上添加一个color属性。结果,实例对象都能读取该属性。

原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。

总结:原型对象的作用,就是定义所有实例对象共享的属性和方法。这也是它被称为原型对象的含义,而实例对象可以视作从原型对象衍生出来的子对象。即让所有实例对象共享它包含的属性和方法,不必在构造函数中定义对象实例的信息
优点:可以让所有实例对象共享它包含的属性和方法


原型链

“原型链”的作用是,读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。

如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”

代码:

<script type="text/javascript">
var Person = function () { };
var p = new Person();
script>


new的过程可以分为三步:

var p={}; 也就是说,初始化一个对象p。

p.proto=Person.prototype;

Person.call(p);也就是说构造p,也可以称之为初始化p。

proto是每个对象都会在其内部初始化一个属性,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去proto里找这个属性,这个proto又会有自己的proto,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

相关函数

instanceof运算符

instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。只能用于对象,不适用原始类型的值。

var v = new Vehicle();
v instanceof Vehicle //true
//等同于
Vehicle.prototype.isPrototypeOf(v)


instanceof运算符的左边是实例对象,右边是构造函数。它的运算实质是检查右边构建函数的原型对象,是否在左边对象的原型链上。对于那些不存在原型链的对象,就无法判断。

hasOwnProperty函数

hasOwnProperty函数判断一个对象是否包含自定义属性而不是原型链上的属性,处理属性但是不查找原型链的函数。

Date.hasOwnProperty('length')
// true

Date.hasOwnProperty('toString')
// false


getOwnPropertyNames

返回一个数组,成员是对象本身的所有属性的键名,不包含继承的属性键名。

Object.getOwnPropertyNames(Date)
// ["parse", "arguments", "UTC", "caller", "name", "prototype", "now", "length"]


Object.getOwnPropertyNames方法返回所有键名。只获取那些可以枚举的属性,使用Object.keys方法。

isPrototypeOf()

对象实例的isPrototypeOf方法,用来判断一个对象是否是另一个对象的原型。

var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);

o2.isPrototypeOf(o3) // true
o1.isPrototypeOf(o3) // true
//上面代码表明,只要某个对象处在原型链上,isPrototypeOf都返回true。
Object.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false


_
proto
_


_
proto
_
可以改写某个对象的原型对象。

var obj = {};
var p = {};

obj.__proto__ = p;
Object.getPrototypeOf(obj) === p // true


将p对象设为obj对象的原型。

尽量少用这个属性,而是用Object.getPrototypeof()(读取)和Object.setPrototypeOf()(设置),进行原型对象的读写操作。

获取原型对象方法的比较

三种方法:

obj.
_
proto
_


obj.constructor.prototype

Object.getPrototypeOf(obj)

前两种都不是很可靠。最新的ES6标准规定,
_
proto
_
属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype在手动改变原型对象时,可能会失效。

推荐使用第三种Object.getPrototypeOf方法,获取原型对象。

var o = new Object();
Object.getPrototypeOf(o) === Object.prototype
// true
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: