-
构造函数
是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。
人话:用来把一个对象构建起来的函数(给这个对象设定属性啊参数啊定义之类的),就叫构造函数。function Foo (name, age) { //构造函数首字母大写 this.name = name; this.age = age; this.class = 'class-1'; return this; } var f1 = new Foo (' zhangsan ', 20); var f2 = new Foo (' zhangsan ', 20); //Foo就是f1和f2的构造函数。
帮助理解
var a = {} 其实是var a = new Object() 的语法糖。
var a = [] 其实是var a = nwe Array() 的语法糖。
function Foo () {} 相当于 var Foo = new Function()
-
使用 instanceof 判断一个函数是否是一个变量的构造函数
后面出现的Js内置函数,就是等号前面变量的构造函数
-
原型规则
- 所有引用类型(对象、数组、函数),都有对象特性,即都可以自由扩展属性。
var obj = {}; obj.a = 100; var arr = []; arr.a = 100; function fn () {}; fn.a = 100; //都可以去给他们添加属性。
- 所有的引用类型(对象、数组、函数),都有一个 " __proto__ " 属性(约定称之为隐式原型),属性只是一个普通的对象。
console.log (obj.__proto__); console.log (arr.__proto__); console.log (fn.__proto__); //符合第一条规则,可以自由拓展属性。
- 所有的函数,都有一个 “ prototype ” 属性(约定称之为显示原型),属性值也是一个普通对象。
console.log (fn.prototype); //函数也是引用类型,所以同时也符合第一条。
- 所有的引用类型(对象、数组、函数), " __proto__ " 属性值指向它的构造函数的 “ prototype ” 属性值
console.log (obj.__proto__ === Object.prototype); //true //obj是一个对象,而Object就是obj的构造函数。符合这一条
-
当试图得到一个对象(函数、数组)的某个属性时,如果对象本身没有该属性,就会去该对象的 __proto__(即该对象的构造函数的prototype)中寻找。
//创建一个构造函数Foo function Foo (name, age) { this.name = name; }; //给Foo的显示原型添加一个属性(函数) Foo.prototype.alertName = function () { alert (this.name); }; //创建对象 var f = new Foo ('zhangsan'); //Foo 就是 f 的构造函数 f.printName = function () { console.log (this.name); }; //测试 f.printName (); //f 本身有这个属性,所以没问题。 f.alertName (); //f 本身没有这个属性,所以就去f.__proto__里寻找, //即到它的构造函数Foo的prototype里寻找,并且可以找到。 //里面的this永远只想自身f
- 补充——循环对象自身的属性
当我们循环获取对象自身属性的时候,并不希望获取到其隐式原型(其构造函数的显示原型)的属性。var item; for (intem in f) { if (f.hasOwnProperty(item)) { cosole.log (item); //虽然浏览器会在for in中屏蔽原型属性,但加上会保证健壮性。 } }
- 所有引用类型(对象、数组、函数),都有对象特性,即都可以自由扩展属性。
-
原型链
在上面,我们可以了解到,f.printName () 和 f.alertName () 是可以被找到的。
但如果再加上 f.toString () 呢,f 及其 Foo.prototype 中都没有这个属性。上面所说 f.__proto__ 即 Foo.prototype 的属性值就是一个普通对象,也就是说有构造函数即Object。参照上面的原型规则可得出以后流程图。
①
f.\_\_proto__ (Foo.prototype)
中找,找不到。
②f.__proto__.__proto__ (Foo.prototype.__proto__)(Object.prototype)
里找
就找到了。
但是,如果还是找不到呢
③ 继续,到Object.prototype.__proto__
(有完没完?)
④ 到了这里,为了避免死循环,Js规定,这里返回null。
-
instanceof 判断函数是否是构造函数
f instanceof Foo
——判断Foo是否为 f 的构造函数。
答案是肯定的,逻辑是 f 的__proto__ 一层层往上看能否对应到 Foo.prototype在尝试
f instanceof Object
——判断Object
答案也是肯定的。网上找也可以找到 Object.prototype
Wait me back