function Foo(name,age){//构造函数首字母大写
this.name = name
this.age = age
this.class = 'class=1'
//return this这行是默认的 就是当new一个当前函数的时候 this是空的 然后赋值 然后return出来
}
var f = new Foo('zhangsan',20)
-
所有的引用类型都有构造函数
var a = {} 其实是一个 var a = new Object()的语法糖
var a = [] 其实是一个 var a = new Array()的语法糖
function Foo(){…} 其实是var Foo = new Function(…)
使用 instanceof 判断一个函数是否是一个变量的构造函数 -
5条原型规则
1.所有的引用类型(数组,对象,函数)都具有对象特性 即可自由扩展属性 除了(‘null’)意外 自由扩展属性例如:以下例子都可扩展一个a属性
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn(){}
fn.a = 100
2.所有的引用类型 (数组 对象 函数)都有一个_proto_属性 属性值是一个普通对象 隐式原型
console.log(obj._proto_)
console.log(arr._proto_)
console.log(fn._proto_)
3. 所有的引用类型 (数组 对象 函数)都有一个prototype属性 属性值是一个普通对象 显示原型
console.log(fn.prototype)
4.所有的引用类型 (数组 对象 函数),_protp_属性值指向它的构造函数的'prototype'属性值
console.log(obj._proto_===Object.prototype)
5.当试图得到一个对象的某个属性时 如果这个对象本身没有这个属性 那么会去他的_proto_
(即它的构造函数的prototype)中寻找
- 当new的时候发生了
1.创建了一个新对象 这个对象的类型是object 作为将要返回的对象实例
2.将这个空对象的原型 指向了构造函数的prototype属性
3.将这个空对象赋值给函数内部的this关键字
4.开始执行构造函数内部的代码 如果构造函数有返回值 则以该对象作为返回值 若没有返回值 或 返回了基本类型 则上述的新对象作为返回值
回顾了这些作用,我们就可以着手来实现功能了
function create(Con, ...args) {
let obj = {}
Object.setPrototypeOf(obj, Con.prototype)
let result = Con.apply(obj, args)
return result instanceof Object ? result : obj
}
- 复制代码这就是一个完整的实现代码,我们通过以下几个步骤实现了它:
- 首先函数接受不定量的参数,第一个参数为构造函数,接下来的参数被构造函数使用
- 然后内部创建一个空对象 obj
因为 obj 对象需要访问到构造函数原型链上的属性,所以我们通过 setPrototypeOf 将两者联系起来。这段代码等同于 obj.proto = Con.prototype - 将 obj 绑定到构造函数上,并且传入剩余的参数
判断构造函数返回值是否为对象,如果为对象就使用构造函数返回的值,否则使用 obj,这样就实现了忽略构造函数返回的原始值
- 总结
- 每个函数都有prototype属性 每个对象都有__proto__属性 ,所有的实例都是对象,但是所有的对象不一定是实例,new出来的对象里面的__proto__指向了构造函数的prototype属性 所以new出来的对象可以通过__proto__.constructor === 构造函数.prototype.constructor来调用构造函数自身,__proto__与prototype一个是隐式原型一个是显示原型 都是用来实现原型的继承和共享 但是隐式原型还有用来实现构成原型链
- Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它
- Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它
- Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建
- 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
- 函数的 prototype 是一个对象,也就是原型
- 对象的 proto 指向原型, proto 将对象和原型连接起来组成了原型链