任何一个函数都可以被new,new了之后,就成了构造方法。
如下:
Copy function Foo (name , age) {
this .name = name;
this .age = age;
//retrun this; //默认有这一行。new一个构造函数,返回一个对象
}
var fn1 = new Foo ( 'smyhvae' , 26 );
var fn2 = new Foo ( 'vae' , 30 ); //new 多个实例对象 与普通函数相比,构造函数有以下明显特点:
不需要用return显式返回值的,默认会返回this,也就是新的实例对象。
参考链接:
当new之后,this会先变成一个空对象,然后通过this.name = name来赋值。
上图中发现,数组、对象、函数也有构造函数,它们的构造函数是Array、Object、funtion。实际开发中,都推荐前面的书写方式。
原型规则是学习原型链的基础。原型规则有五条,下面来讲解。
所有的引用类型(数组、对象、函数),都具有对象特性,都可以自由扩展属性 。null除外。
举例:
所有的引用类型 (数组、对象、函数),都有一个_proto_属性,属性值是一个普通的对象 。_proto_的含义是隐式原型。
其实,规则2是规则1的特例,只不过,js语法帮我们自动加了 规则2。
所有的函数 (不包括数组、对象),都有一个prototype属性,属性值是一个普通的对象 。prototype的含义是显式原型 。(实例没有这个属性)
所有的引用类型 (数组、对象、函数),_proto_属性指向它的构造函数 的prototype值。
总结:以上四条,要先理解清楚,然后再来看下面的第五条。
当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_中寻找(即它的构造函数的prototype)。
举例代码1:
上方代码中,虽然 alertName 不是 fn 自身的属性,但是会从它的构造函数的prototype里面找。
扩展: 遍历循环对象自身的属性
我们知道,for ... in循环可以遍历对象。针对上面的那个fn对象,它自身有两个属性:name、printName,另外从原型中找到了第三个属性alertName。现在,如果我们对fn进行遍历,能遍历到两个属性还是三个属性呢?
答案:两个。因为,高级浏览器中已经在 for ... in 循环中屏蔽了来自原型的属性。但是,为了保证代码的健壮性,我们最好自己加上判断 ,手动将第三个属性屏蔽掉:
还是拿上面的举例代码1举例,如果此时在最后面加一行代码:
上面的代码中,fn直接调用了 toString()方法,这是因为它通过原型链 ,去_proto_的_proto_里找到了Object,而Object是由toString()方法的。
格式:
instanceof的作用:用于判断引用类型 属于哪个构造函数 。
例1:判断一个变量是否为数组: 变量 instanceof Array
例2:
例3:
上面这句话,判断逻辑是:fn 的 _proto_ 一层一层往上找,看能否对应到 Foo.prototype 。
原型链如下:(重要)
注意,Object这个构造方法的显式原型是null,这是一个特例。
下面分别讲解。
题目一:如何准确判断一个变量时数组类型
答案:
上方代码表明,只能通过 instanceof 来判断是否为数组。而 typeof 的打印结果是 object。
题目二:写一个原型链继承的例子
来看个基础的代码:
上面这个例子是基础,但是,在回答面试官的问题时,不要写上面的例子。要写成下面这个例子:(更贴近实战)
举例: 写一个封装DOM查询的例子
这个例子有点像 jQuery 操作DOM节点。
表示这个例子,略难。
题目三:描述 new 一个对象的过程
(1)创建一个新对象
(2)this 指向这个新对象
(3)执行代码(对this 赋值)
(4)返回this
参考链接: