javascript原型及原型链详解

原型是function对象的的属性,原型也是对象


构造函数构造出来的实例能够继承原型上的属性和方法

如下例子

// Person.prototype  --  原型
Person.prototype = {}
Person.prototype.name = 'abc'
function Person() {
    this.age = 24 
}
var person = new Person()
console.log(person.name)   //abc
var person1 = new Person()
console.log(person1.name)  //abc
person.name = 'lyj'  //给自身新增一个name属性,不能通过子代修改原型上面的name属性, 也不能删除和新增
console.log(person.name)   //lyj
console.log(person1.name)  //abc
console.log(Person.prototype.name)  //abc

再看一下例子

function Car() {

}
var car = new Car()
//查看实例对象的构造函数
console.log(car.constructor)  // function Car() {}
//原因是原型上系统会默认增加constructor属性指向构造函数
// Car.prototype = {
//     constructor: Car
// }
console.log(Car.prototype.constructor)

//这个constructor可以被修改
function Person() {

}
Car.prototype.constructor = Person
var car1 = new Car()
console.log(car1.constructor)

再看一下例子

Person.prototype.name = 'abc'
function Person() {
  // var this = {
  //     __proto__: Person.prototype
  // }
  // 构造函数构造时会隐式的在this上加上 __proto__ 属性,指向 Person.prototype 即原型
}
var person = new Person()
console.log(person.__proto__ === Person.prototype)  //true
// 实例的 __proto__ 能够被修改
console.log(person.name)
var obj = { name: 'lyj' }
person.__proto__ = obj   //person的原型指向了obj
console.log(person.name)

 再看以下例子

Person.prototype.name = 'sunny'
function Person() {
}
var person = new Person()
Person.prototype.name = 'chery'
console.log(person.name)  // chery
--------------------------------------------------------
Person.prototype.name = 'sunny'
function Person() {
}
var person = new Person()
Person.prototype = {
  name: 'chery'
}
console.log(person.name)  // sunny

---------------------------------------------------------
//类似下面形式 var obj = {name: 'sunny'} var obj2 = obj obj = {name: 'chery'} console.log(obj2.name)
Person.prototype.name
= 'sunny' __proto__ = Person.prototype Person.prototype = {name: 'chery'} console.log(__proto__.name) 'sunny'
--------------------------------------------------------
Person.prototype.name
= 'sunny' function Person() { } Person.prototype = {   name: 'chery' } var person = new Person() console.log(person.name) // chery

再看以下例子

Person.prototype.obj = {
  name: 'abc'
}
function Person() {
}
console.log(Person.prototype.__proto__ === Object.prototype)  //true
//函数原型的最终原型就是Object的原型Object.prototype, 也是所有对象的最终原型

var person = new Person()
//修改原型的属性
console.log(person.obj.name) //abc
person.obj.name = 'lyj'  //不会在实例对象上新增obj对象及属性,而是在原型上修改,但特仅限于引用类型,基本类型不行
console.log(person.obj.name) //lyj

再看以下例子

Person.prototype = {
  name: 'abc',
  sayName: function() {
    console.log(this.name)
  }
}
function Person() {
  this.name = 'lyj'
}
var person = new Person()
person.sayName()  //lyj
Person.prototype.sayName()  //abc
//谁调用,this指向谁

再看以下例子

var obj = Object.create(原型)  指定对象的原型
var obj = {name: 'abc'}
var obj1 = Object.create(obj)
console.log(obj1.name)

//绝大多数对象最终会继承Object.prototype
//个别不会 比如通过 Object.create创造出来的原型且是null
var obj = Object.create(null)  
console.log(obj) //没有__proto__ ,且也不能认为的添加 __proto__
//Object.create()参数里面只能放 object 和 null

//undefined和null没有toString()方法
//string. number, boolean有toString()方法是因为会转化为包装类,这些包装类上有toString()方法

//重新,子代上实现和原型上一样的功能方法

var obj = 123
document.write(obj) //123
var obj = {}
document.write(obj) //[object Object]
var obj = Object.create(null)
document.write(obj) //报错   因为输出到页面中会默认调用toString方法,而用原型null创造的obj是没有toString()方法
obj.toString = function() {
  return 'hello'
}
document.write(obj)  //hello   默认会调用obj上的toString()方法

end !!!

原文地址:https://www.cnblogs.com/lyjfight/p/13815214.html