JavaScript创建对象的三种方式

144 阅读3分钟

创建对象和原型链

1.创建对象的三种方式

  1. 字面量
  2. 构造函数
  3. Object.create
//1.字面量方式
var obj1 = {name: 'TOM'}
//上下二者等价
var obj2 = new Object(name: `TOM`)
//2.构造函数方式
var M = function (name){
    this.name = name
}
var obj3 = new M('TOM')
//2.Object.create方式
var p = {name:'TOM'}
var obj4 = Object.create(p)//原型链连接
//obj4是实例,name是p原型的属性,构造函数是Object

2.原型、构造函数、实例和原型链

构造函数

为什么需要原型?

看看以下例子..

function Person(name, age, gender) {
    this.name = name
    this.age = age
    this.gender = gender
    this.sayName = function () {
        alert(this.name);
    }
}
var per1 = new Person("孙悟空", 18, "男");
var per2 = new Person("唐僧", 78, "男");

这样创建对象,每创建一个实例对象,该实例对象就会自带一个sayName方法,如果创建成千上万个实例对象,就会有成千上万个sayName方法。那么为什么不可以把所有实例对象都拥有的方法放在一个地方呢?------原型

从而就诞生了原型!

原型

原型对象就相当于一个公共区域,所有同一个类中的实例对象都可以访问到它

image-20211202114026838

构造函数把所有实例拥有的方法放到了原型对象上面,并且通过prototype可以访问到原型对象。

原型链

任何一个实例都可以通过原型链找到它上面的原型,该原型对象中的方法和属性可以被所有原型实例共享。

__proto__:每个对象数据类型天生自带__proto__

原型链中有一个constructor属性,它指向构造函数对象。

image-20211202115450727

例题

function User() {}
User.prototype.sayHello = function () {};
​
var u1 = new User();
var u2 = new User();
​
console.log(u1.sayHello === u2.sayHello); //true
/**
       * u1的__proto__和u2的__proto__都是指向构造函数User的prototype,
       * User.prototype的身上有sayHello方法,所以结果为true
       */
console.log(User.prototype === Function.prototype); //false
/**
       * User.prototype的__proto__指向Function.prototype,所以结果为false
       */
console.log(User.__proto__ === Function.prototype); //true
/**
       *User是一个构造函数,那么它的隐式原型就指向Function.prototype
       */
console.log(User.__proto__ === Function.__proto__); //true
/**
       *
       */
console.log(u1.__proto__ === u2.__proto__); //true
/**
       * u1的__proto__和u2的__proto__都是指向构造函数User的prototype,所以结果为true
       */
console.log(u1.__proto__ === User.__proto__); //false
/**
       * u1.__proto__指向User.prototype,而User.__proto__指向Function.prototype
       */
console.log(Function.__proto__ === Object.__proto__); //true
/**
       * Function.__proto__是指向Object的
       * Object.__proto__指向Object.prototype
       */
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); //false
/**
       * 因为在JS里面万物皆对象,而Function又是对象的一个分支,所以Function的显式原型就是Object
       * Function.prototype.__proto__指向Object.prototype
       * Object.prototype.__proto__指向null
       */
console.log(Function.prototype.__proto__ === Object.prototype); //true
/**
       * Function.prototype指向Object,再加上__proto__就是指向Obeject.prototype
       */

image-20211202181656094

3.instanceof

const obj = {}
const arr = []
console.log(typeof obj) //Object
console.log(typeof arr) //Object

以上二者都会打印Object,因为在JavaScript中万物皆对象,Array也属于对象,这样就分辨不出来对象和数组。

那么这里可以用到instanceof关键字

const obj = {}
const arr = []
console.log(obj instanceof Array)   //false
console.log(arr instanceof Array)   //true

instanceof的作用:判断实例属于哪个构造函数

instanceof的原理:判断实例对象的__proto__属性和构造函数的prototype属性是否为同一个引用。

注意

在多层原型链上面,如果在第一层原型没有找到就会往上继续找一直找到最后的原型。只要在这条原型链上可以找到实例是某一构造函数的,那么就会返回true;否则返回false。

另外,instancerof关键字并不能判断基本数据类型。

image-20211202190602922

\