4、原型和面向对象

实例化和原型

在JavaScript中,使用原型定义的属性和功能会自动应用到对象的实例上,一但进行了定义,原型的属性就会变成实例化对象的属性。所有函数初始化的时候都有一个prototype属性表示原型。

// 定义一个函数
function A() {}

// 在其原型上添加属性
A.prototype.go = function () {return true;};

// 将函数赋值给变量,空函数无返回值
var a1 = A();
console.log(a1);  // undefined

// 将函数作为构造器进行实例化赋值给变量
var a2 = new A();

// 变量成为一个实例
console.log(a2); // A {}

// 该实例继承了函数原型上的属性
console.log(a2.go()); // true

使用new操作符将函数作为构造器进行调用时,其上下文会被定义为新对象实例。这就表明,在构造器函数内部,可以使用this参数初始化值。在构造器内的绑定操作优先级会高于在原型上的绑定操作优先级,因为构造器的this上下文指的是实例自身。

// 使用同样的名称为构造器和原型添加属性
function A() {
    this.x=1;
}
A.prototype.x = 2;

// 实例继承属性时,构造器本身的属性会覆盖原型上的属性
var a1 = new A();
console.log(a1.x);  // 1

原型的改变会影响其构造器已经创建的实例对象。

// 创建构造函数并实例化
function A() {}
var a1 = new A();

// 改变其原型,已经实例化的对象上继承的属性也会被修改
A.prototype.x = 1;
console.log(a1.x);

每个JavaScript对象都有一个隐式属性constructor,该属性引用的是创建该对象的构造器。

function A() {}
var a1 = new A();
A.prototype.x = 1;
// 使用a1.constructor.prototype.x可以访问到原型上的x属性,证明了原型是实时附加在对象上的,所以在创建实力之后,更改原型也会生效。
console.log(a1.constructor.prototype.x);  // 1

查找属性时,首先查找对象自身,如果没有找到,再查找构造器的原型。

function A() {
    this.x=1;
    this.y=2;
}
var a1 = new A();
A.prototype.y=1;
// 实例化的对象a1已经具有了y属性,即使在实例化之后再为构造器的原型添加新的y属性,也不会覆盖实力中的原来的y属性。
console.log(a1.y);  // 2

利用constructor属性,可以在不知道原有构造器的情况下,利用已有的实例来创建新的实例。

function A() {}
var a1 = new A();
var a2 = new a1.constructor();
// a1与a2指向的不是同一个实例
console.log(a1 !== a2); // true

疑难陷阱

扩展原生Object.prototype时,所有对象都会接受这些额外的属性。当我们遍历对象的属性时,这些额外的属性也会被遍历。

// 为原生Object.prototype添加keys方法,返回一个属性名组成的数组。
Object.prototype.keys=function () {
    var key = [];
    for(var p in this){
        key.push(p);
    }
    return key;
};
var obj = {
    a:1,
    b:2,
    c:3
};
// keys方法本身被继承,也成为了实例obj的属性之一
console.log(obj.keys());  // ["a", "b", "c", "keys"]

使用hasOwnProperty()方法可以判断属性是实例自身的,还是继承自原型的

Object.prototype.keys=function () {
    var key = [];
    for(var p in this){
        // 判断属性是来自实例自身还是继承自原型
        if(this.hasOwnProperty(p)){
            key.push(p);
        }
    }
    return key;
};
var obj = {
    a:1,
    b:2,
    c:3
};
console.log(obj.keys()); // ["a", "b", "c"]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容