Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[js] 第58天 请说下你对__proto__和prototype的理解 #242

Open
haizhilin2013 opened this issue Jun 12, 2019 · 8 comments
Open

[js] 第58天 请说下你对__proto__和prototype的理解 #242

haizhilin2013 opened this issue Jun 12, 2019 · 8 comments
Labels
js JavaScript

Comments

@haizhilin2013
Copy link
Collaborator

第58天 请说下你对__proto__和prototype的理解

@myprelude
Copy link

myprelude commented Jun 13, 2019

  • 只有函数对象才有prototype属性;prototype对象上存放共用的方法和属性
  • 对象都有__proto__属性,__proto__是指向该对象构造函数的原型属性(即prototype)
function Parent(name){
  this.name = name
}
Parent.prototype = {
  contructor:Parent,
  speak:function(){
    console.log(`我是${this.name}`)
  }
}
var children = new Parent('xiaoming')
children.name  // xiaoming
children.speak() // 我是xiaoming
children.__proto__ ===Parent.prototype  // true       
Parent.prototype.__proto__ === Object.prototype  // true  
children.toString()  // "[object Object]"

上面可以看出通过__proto__属性我们可以拿到Object原型对象上的属性和方法,原型对象上的__proto__又指向该构造函数的prototype,从而形成了一条原型链。上面children能够使用toString方法的原因。

@haizhilin2013 haizhilin2013 added the js JavaScript label Jun 18, 2019
@qingleizhang123
Copy link

qingleizhang123 commented Jun 24, 2019

1.首先理解一个概念,JS里面万物皆对象,而对象又可分为普通对象和函数对象。

2.第二点,需要理解面向对象的另一个概念——构造函数

我们知道,在js里面一切都是对象,那么对象的创建方法有哪些呢?

1. 字面量来创建对象,即
var person1={
    name:"jayray",
    age:"26",
    job:"software Engineer"
};
2. 通过new关键字来创建对象,即
var person1=new Object(name="jayray",age="26",job="software Engineer");

其中,Object()即构造函数,虽然通过字面量或Object()构造函数可以创建单个对象,但是当需要创建多个对象时会产生大量的重复代码
这里通过new操作符创建一个对象实际上会经历4个步骤:

  1. 创建一个对象;
  2. 将构造函数的作用域赋给新对象(即this指向了这个新对象);
  3. 执行构造函数中的代码(为新对象添加属性和方法);
  4. 返回新对象;
3. 工厂模式来创建对象,即
function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o,sayName=function(){
        alert(this.name);
    }
}

var person1=createPerson("张三","24","学生");
var person2=createPerson("李四","30","老师");

函数createPerson()能够根据接受的参数来构建一个Person对象,这种方式即工厂模式,可以解决创建多个相似对象的问题,但却没有解决对象识别的问题。

4. 构造函数模式
function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    }
}

var person1= Person("张三","24","学生");
var person2= Person("李四","30","老师");

其中,Person()函数取代了createPerson()函数,且函数名Person的使用是大写字母P,即OO语言的特点。person1和person2分别保存着Person构造函数的一个实例,且这两个对象都有一个constructor(构造函数)属性,该属性指向实例的构造函数,即Person。

console.log(person1.constructor==Person);// true

对象的consturctor属性可以用来标识对象类型,但是检测对象类型,用instanceof操作符更可靠。

至此,我们了解了js对象的创建方法以及构造函数的概念,那么回到第一点,我们怎样区分JS里面的普通对象和函数对象。简单点来说,可以通过构造函数的类型进行区分,即对象的构造函数为Function的为函数对象,对象的构造函数为Object的为普通对象。

3.第三点,需要理解的就是原型对象的概念

js里面,创建的每一个函数对象,都有一个prototype(原型)属性,这个属性是一个指针,指向函数的原型对象。所有原型对象默认都会自动获得一个constructor(构造函数)属性,这个属性指向prototype属性所在的函数。

当我们调用构造函数创建一个实例后,该实例的内部会包含一个指针,指向构造函数的原型对象,即_proto_指针。因此,所有的普通对象都会存在_proto_属性。

举例如:

var person1=new Person();

Person.prototype即构造函数的原型对象,而原型对象都自动获得constructors属性,指向构造函数,因此Person.prototype.constructor=Person。
person1为构造函数Person()的实例,即普通对象,都会存在一个内部属性_proto_,指向实例的构造函数的原型对象,因此person1.proto=Person.prototype。
由构造函数模式创建对象的概念可知,每个实例对象都有一个constructor属性,指向实例的构造函数,而原型对象都会获得constructor属性,指向构造函数,那么我们由此可以推断,原型对象是构造函数的一个特殊实例。

console.log(person1.constructor==Person);// true
console.log(Person.prototype.constructor=Person);//true

@monxiaolee
Copy link

  • js里所有的对象都有proto属性(对象,函数),指向构造该对象的构造函数的原型。

  • 只有函数function才具有prototype属性。这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。

@Vi-jay
Copy link

Vi-jay commented Jul 31, 2019

const protoObj = {name: 1};
function Human() {}
Human.prototype = protoObj;
const vijay = new Human();
console.log(vijay.__proto__ === Human.prototype, Human.prototype === protoObj);//true true

@seho-dev
Copy link

自己总结了一把:

https://www.yinzhuoei.com/index.php/archives/116/

@MrZ2019
Copy link

MrZ2019 commented Nov 24, 2020

  • 只有函数对象才有prototype属性;prototype对象上存放共用的方法和属性
  • 对象都有__proto__属性,__proto__是指向该对象构造函数的原型属性(即prototype)
function Parent(name){
  this.name = name
}
Parent.prototype = {
  contructor:Parent,
  speak:function(){
    console.log(`我是${this.name}`)
  }
}
var children = new Parent('xiaoming')
children.name  // xiaoming
children.speak() // 我是xiaoming
children.__proto__ ===Parent.prototype  // true       
Parent.prototype.__proto__ === Object.prototype  // true  
children.toString()  // "[object Object]"

上面可以看出通过__proto__属性我们可以拿到Object原型对象上的属性和方法,原型对象上的__proto__又指向该构造函数的prototype,从而形成了一条原型链。上面children能够使用toString方法的原因。

@xiaoqiangz
Copy link

只有函数对象才有prototype属性,这个属性是一个指针,指向一个构造函数的原型对象,这个对象包含所有实例共享的属性和方法。
每个创建的实例对象都有一个__proto__属性,用于指向构造函数的原型对象(prototype),通过__proto__属性我们可以拿到父层对象上的属性和方法,父层对象的__proto__又指向祖先层对象上的(prototype)属性和方法,这样形成了一条链条,直至找到最上层的Object.prototype为止,这也就是原型链。

@shengjie9
Copy link

函数对象特有prototype原型属性;prototype对象上由constructor和共用的属性和方法组成
每个创建的对象实例都有__proto__属性,__proto__属性指向创建实例的函数的原型

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js JavaScript
Projects
None yet
Development

No branches or pull requests

9 participants