function Test(){}
let test=new Test()
在这一过程中,这个新对象的内部的__proto__属性被赋值为构造函数的prototype属性
test.__proto__===Test.prototype
对象的constructor性指向构造函数
test.constructor==Test//这里的test.constructor相当于Test.prototype.constructor
instanceof操作符是用来确认对象类型的,(用来检测某个对象是不是另一个构建函数的实例)
test instanceof Test
构造函数与普通函数的区别? 它们唯一不同的就是调用方式的不同。任何函数只要使用new操作符调用就是构造函数,否则就是普通函数 为什么会有原型链?它主要解决了什么问题?
function Person(name,age){
this.name=name
this.age=age
this.sayName=function(){
console.log(this.name)
}
}
const person1=new Person('11',11)
const person2=new Person('22',22)
在创建实例时,这里的this.sayName相当于
this.sayName=new Function("console.log(this.name)")
这里新创建的Function的机制是一样的,可以有优化
function Person(name,age){
this.name=name
this.age=age
this.sayName=sayName
}
function sayName(){
console.log(this.name)
}
const person1=new Person('11',11)
const person2=new Person('22',22)
但这样不好的是会有大量的全局作用域的函数.针对这种情况。原型链可以解决这个问题 每个函数都会创建一个prototype属性,这个属性是一个对象。它包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象 就是 通过调用构造函数创建的对象 的原型
理解原型的本质: 每个函数都会一个prototype属性,指向原型对象。[Person.prototype是个对象] 每个原型对象自动获得一个constructor属性,指向构造函数 Person.prototype.constructor==Person 创建构造函数创建的实例的内部属性__proto__指针就会被赋值为构造函数的原型对象 即person.proto===Person.protytpe 关键点:实例与构造函数之间没有关系,但与构造函数原型之间有直接的联系
这个参数constructor主要是针对原型对象来说的 Person.prototype?[是的]
有些实现没有对外暴露__proto__方法,但可以通过函数isPrototypeOf来检查两个对象之间的关系
Person.prototype.isPrototypeOf(person1)
或者通过Object.getPrototypeOf()来返回对应的原型对象
Object.getPrototypeOf(person1)===Person.prototype //返回为true
原型链之间的这种关系可以通过Object.create()来联接
let bird={name:1}
let perosn=Object.create(bird)
Object.getPrototypeOf(person)===bird //true
hasOwnProperty()可以用来确定某个属性是在实例上还是在对应的原型对象上
person.hasOwnProperty('name')
in操作符 in操作符会在可以通过对象访问指定属性时,返回true.无论该属性是在实例上还是在原型上
console.log('name' in person1) //因此可以in 和 hasOwnProperty()结合着来使用
原型最大的问题在于它的共享特性(特别是对于引用值 类型来说)(也有其他问题,比如弱化了向构造函数传递初始化参数的能力,会导致所有实例取到相同的值)
function Person(){
}
Person.prototype={
name:['one','two']
}
const person1=new Person()
const person2=new Person()
person1.name.push("three")
//这样person2的name值也发生了变化
因此就出现了继承 原型链与继承的关系 可以用instanceof操作符(如果一个实例的原型链中出现过相应的构造函数,则返回true)
person instanceof Person
//手动实现instanceof
let myInstanceof = (target,origin) => {
while(target) {
if(target.__proto__===origin.prototype) {
return true
}
target = target.__proto__
}
return false
}
let a = [1,2,3]
console.log(myInstanceof(a,Array)); // true
console.log(myInstanceof(a,Object)); // true
function Person(name){
this.name=name
}
const p=new Person("one")
1.new创建了一个对象,这个对象的原型链,指向了构造函数的原型
p.__proto__==Person.prtototype
2.Person有个原型,原型上有个construcotr,是Person自己
Person.prototype.construcotr==Person
手写一个new函数 1创建了一个对象 2这个对象的原型指向了Function的prototype 3该对象调用了Function的方法 4根据一些特定情况进行返回 a如果构造函数明确返回一个对象,则返回这个对象、 b如果这个构造函数没有返回值或者返回一个非对象类型,则new最后返回创建的这个对象
function newFunc(Person,..res){
if(typeof Person!=='function'){
throw new Error("eror")
}
var obj=Object.create(Person.prototype)
var result=Person.call(obj,rest)
return result&& typeof result=='object' ?result:obj
}
怎样实现Oject.create()
function inherit(p){
if(p==null)t throw new Error('error')
if(Object.create) return Object.create(p)
if(typeof p!='object' && typepof p!='function') return new Error('error')
function F(){}
F.prototype=p
return new F()
}
原型继承的例子及缺点
function Person(){
this.name=[]
}
Person.prototype.getName=function(){return this.name}
function Child(){}
Child.prototype=new Person()
Child. .constructor=Child
//1child不能传参
//2如果parent有引用类型的属性,一修改,都会受影响
组合寄生继承
function Parent(name){
this.name=name
}
Parent.prototyp.getName=function(){}
function Child(name){
Parent.call(thsi,name)//这里是执行了Parent()方法
}
Child.prototype=Object.create(Parent.prototype)
//Child.prototype=new Parent()
Child.prototype.constructor=Child
组合寄生与class的区别 class继承会继承静态属性 子类中,必须在constructor中调用super.因为子类自己的this对象,必须先通过父类的构造函数来完成