javascript中的对象

1 创建对象

在js中创建对象非常的简单

var obj={}

这样,我们就创建了一个对象

2 对象的继承

在ES6之前,javascript对象的继承是通过原型(prototype)来实现的。在ES6之后的继承方式类似于java

2.1 方式1 通过prototype创建对象

举例

var student = {
    name: 'no_name',
    height: 1.2,
    run: function () {
        console.log(this.name + ' is running...');
    }
};

var xiaoming = {
    name: '小明'
};

xiaoming.__proto__ = student;

访问属性和方法

xiaoming.name; // '小明'
xiaoming.run(); // 小明 is running...

xiaoming有自己的name属性,但并没有定义run()方法。不过,由于小明是从student继承而来,只要studentrun()方法,xiaoming也可以调用

 

需要注意的是,上述示例只用于演示,在平时开发过程中不要直接用obj.__proto__去改变一个对象的原型。

2.2 通过Object.create()创建对象

var xiaoming=Object.create(student)
xiaoming.name='小明'
//判断原型是否是student
xiaoming.__proto__===student // 返回true

2.3 通过构造函数创建对象

定义一个构造函数

function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
}

咦,这不就是一个普通函数吗。是的,这确实就是一个普通函数,但是如果我们通过如下方式使用,则这个普通函数就是一个构造函数

//通过构造函数创建一个新的对象
var xiaoming=new Student('小明')
//调用
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!

新创建的xiaoming的原型链是:

xiaoming ----> Student.prototype ----> Object.prototype ----> null

3 原型链

当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined

例如

var arr = [1, 2, 3];

其原型链是

arr ----> Array.prototype ----> Object.prototype ----> null

再比如

function foo() {
    return 0;
}

函数也是一个对象,它的原型链是:

foo ----> Function.prototype ----> Object.prototype ----> null

4 constructor属性

new Student()创建的对象还从原型上获得了一个constructor属性,它指向函数Student本身

xiaoming.constructor === Student.prototype.constructor; // true
Student.prototype.constructor === Student; // true
Object.getPrototypeOf(xiaoming) === Student.prototype; // true
xiaoming instanceof Student; // true

这是什么乱七八糟的,看晕了,请看下图

 

其中红色箭头是原型链,注意,

构造函数Student.prototype指向的对象就是xiaoming的原型对象,这个原型对象自己还有个属性constructor,指向Student构造函数本身。

另外,构造函数Student恰好有个属性prototype指向xiaoming的原型对象,但是xiaoming对象可没有prototype这个属性,不过可以用__proto__这个非标准用法来查看。

不过还有个问题

xiaoming.name; // '小明'
xiaohong.name; // '小红'
xiaoming.hello; // function: Student.hello()
xiaohong.hello; // function: Student.hello()
xiaoming.hello === xiaohong.hello; // false

xiaoming和xiaohong各自的name不同,这是对的

但是xiaoming和xiaohong各自拥有独立的hello()方法,这就不合理了,这样浪费了很多内存。解决方法是有的,就是通过上图的原型链关系图,我们如果把hello()方法移动到他们共同的原型上就可以了,如下图

 

把hello()方法移动到上图中的"某个对象"里,而这个"某个对象"就是Student.prototype,因此我们把hello()方法移动到Student.prototype上。

修改代码如下

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

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

 

posted @ 2022-12-02 09:46  zhenjingcool  阅读(25)  评论(0编辑  收藏  举报