【23】JavaScript(构造函数、this、原型)

1 构造函数

1.1 什么是构造函数

构造函数相当于其他编程语言里的类(ES6 中引入了类的概念),每个对象都有与之对应的构造函数,构造函数描述对象的特性(属性和方法)。对象是构造函数的实例,构造函数是对象的抽象。一个构造函数可以对应多个对象,一个对象只对应一个构造函数。

1.2 判断对象的构造函数

① 运算符 instanceof

二元运算符,返回布尔值。

对象 instanceof 构造函数;

注:

  1. 对象与自己的构造函数,成立

  2. 对象与它的原型链上的对象的构造函数,成立

  3. JS中所有的对象(除了修改过原型链)与 Object 都成立

② constructor 属性

任何一个对象都有该属性,值为该对象的构造函数。

对象.constructor

注:

  1. 每个对象都有constructor属性,但不一定在自己身上(可用hasOwnProperty判断)。对象通过 constructor 属性,能够获取对象的构造函数,但是不是所有的对象都是准确的,如果一个对象上有constructor属性,其值是指向以该对象为原型的对象的构造函数
  2. 对象a 的 原型是对象 b:
    • 对象a本身上没有constructor属性,使用的是原型上的属性,结果得到就是 a 的构造函数。
    • 对象a本身上有constructor,值指向以自己为原型的对象(a)的构造函数。

1.3 自定义构造函数

// 定义构造函数 描述用户信息
function User(username, pwd, address) {
    // 定义实例的属性
    this.username = username;
    this.pwd = pwd;
    this.address = address;

    // 定义实例的方法
    this.addShopcart = function() {
        console.log(this.username + ' 把一件商品加入了购物车!');
    }

    this.addOrder = function() {
        console.log(this.username + ' 下单了, 请送到' + this.address);
    }
}

1.4 实例化

new User();
new User('曹操', '123456', '安徽亳州');

注:

  • 实例化构造函数时,构造函数体中的语句会执行。

  • 构造函数的返回值问题:

    ① 如果构造函数中没有 return 或者 return 的是原始类型的数据(number、string、boolean),实例化得到新的对象,与返回值无关;

    ② 如果构造函数中 return 的是对象类型的数据(如:Array、Function),实例化得到的是返回值。

  • 构造函数本质上仍是函数,即可调用也可实例化。为了区分,一般构造函数的首字母大写。是函数还是构造函数取决于如何使用:如果调用,就是函数;如果实例化,就是构造函数。

2 this

2.1 this的含义

this 是 JS 中内置的一个变量,值由系统给出,通常在函数中使用。

2.2 this的指向(this 的值)

在构造函数中使用this: this 的值是构造函数将来实例化出来的对象。

在函数(方法)中使用this: this的值是调用该函数(方法)的对象。

2.3 window

  • JS中有一个全局对象,所有全局变量都是全局对象的属性,所有全局函数都是全局对象的方法。运行在浏览器上的JS,全局对象是 window
  • 一打开页面,window对象可以自动创建。
  • 使用全局对象的属性和方法,可以把前面的window. 省略。

3 原型

3.1 原型的概念

原型是个对象,每个对象都有原型,对象可以继承原型上的属性和方法。

3.2 如何获取对象的原型

① 隐式获取

对象.__proto__

② 显示获取

对象的构造函数.prototype

注:对象的构造函数.prototype获取的是该构造函数的实例(对象)的原型,不是构造函数自身的原型!

3.3 对象、构造函数、原型之间的关系

① 对象和构造函数

  • 对象是构造函数的实例,构造函数是对象的抽象(描述)。
  • 一个构造函数对应多个对象,一个对象只对应一个构造函数。

② 对象和原型

  • 每个对象都有原型
  • 对象可以继承原型上的属性和方法

③ 构造函数和原型

  • 通过构造函数的 prototype 可以获取其实例(对象)的原型。
  • 默认情况下,构造函数相同的对象,其原型也相同。

3.4 自定义构造函数时原型的应用

自定义构造函数时将方法添加到实例的原型上,这样不必为每一个实例都开辟一块内存空间存放其方法,节省了内存空间。

// 定义用户 构造函数
function User(username, pwd, address) {    
    // 设置实例的属性    
    this.username = username;    
    this.pwd = pwd;    
    this.address = address;
}
// 把方法添加到实例的原型上
User.prototype.addShopcart = function() {    
    console.log(this.username + ' 添加商品到购物车!');
};
User.prototype.addOrder = function() {    
    console.log(this.username + ' 下单了,请邮寄到 ' + this.address);
};

3.5 判断属性是否属于对象本身

判断属性是否是对象本身上的属性,返回布尔值。如果属性在对象本身上,返回 true; 如果属性在对象的原型上或者没有这个属性,返回 false。

对象.hasOwnProperty('属性名');

注:

与 in 运算符的区别:对象本身的属性和原型上的属性,in 运算符都得到 true

3.6 创建对象的同时指定原型

Object.create(原型)

// 创建一个没有原型的对象
Object.create(null); 

// 创建一个新对象,指定[100,200,300]为原型
Object.create([100,200,300]);

4 原型链

4.1 原型链的概念

对象的原型仍然是个对象类型的数据,所以原型也具有原型,直到一个顶层原型对象, 形成了原型链。

4.2 属性查找过程

原型链描述对象中属性的查找过程:

当使用对象中某个属性的时候,先从对象本身查找,如果没有再去原型上查找,还没有继续上层原型查找,直到顶层原型,哪里找到哪里停止查找,如果一直到顶层原型仍然找不到,自动得到 undefined

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容