总结
1. 函数的原型:
每个函数中都有个prototype的属性指向函数的原型,只不过一般的普通函数中的这个属性我们不太关注,一般关注构造函数中的prototype。当创建了构造函数的时候,浏览器中会相应的创建一个原型对象,原型对象也有个constructor指向构造函数。
1.1 通过构造函数创建对象:var 对象名=new 构造函数(参数);
构造函数创建的新对象中有个[[proto]] 是指向构造函数的原型对象,这个属性虽然无法直接访问到,但是可以用protol 来访问原型对象。
<span style="color:#ff9900"><span style="color:#33cc00">function</span><span style="color:#3366ff"> person</span>(<span style="color:#000099">name</span>,<span style="color:#000099">age</span>){
<span style="color:#000066"> this</span>.name=name; //构造函数中的prototype指向了原型对象
<span style="color:#000066"> this</span>.age=age;
}
<span style="color:#009900">var</span> p1=new <span style="color:#3366ff">person</span>("李四",20); //新创建的对象中有个[[proto]]指向构造函数的原型对象。
<span style="color:#ff0000">console</span>.<span style="color:#3366ff">log</span>(<span style="color:#000000">f1</span>);</span>
注意:
①.原型对象中的属性可以手动添加,但是无法修改;
②.原型中的属性和方法,新创建的对象都可以访问和调用;
③.当对象新添加一个属性和原型同名,输出的结果是对象的属性,不是删除了原型的属性,而是覆盖了原型的属性;
④.构造函数中的this 指代的是创建的对象;
1.2 构造函数与普通函数的区别:
区别主要在于调用方式:普通函数直接调用,而构造函数用new来调用。
注意:构造函数首字母尽量大写,尽量不要在构造函数中添加return。
1.3 与原型有关的方法:
hasOwnProperty( ):对象名.hasOwnProperty("属性名");
-
作用:判断一个属性是否存在对象中。
function fn(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
var f1=new fn("李四",20,"男");
console.log(fn.hasOwnProperty("name")); //true
console.log(fn.hasOwnProperty("page")); //false
function fn(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
var f1=new fn("李四",20,"男");
console.log(fn.hasOwnProperty("name")); //true
console.log(fn.hasOwnProperty("page")); //false
in操作符 (属性值 in 对象名):
作用:判断一个属性是否存在原型中。
function fn(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
this.panduan=function (obj,ele){
if(obj.hasOwnProperty(ele)){
alert("属性在对象上")
}else if(ele in obj){
alert("属性在原型中")
}else{
alert("属性不存在");
}
}
}
var f1=new fn("李四",20,"男");
f1.page="ss";
f1.panduan(f1,"page");
function fn(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
this.panduan=function (obj,ele){
if(obj.hasOwnProperty(ele)){
alert("属性在对象上")
}else if(ele in obj){
alert("属性在原型中")
}else{
alert("属性不存在");
}
}
}
var f1=new fn("李四",20,"男");
f1.page="ss";
f1.panduan(f1,"page");
1.4 组合模式
原型优缺点:
构造函数创建的对象,都可以共享原型中的属性和方法,但是一般我们创建的对象的属性不会相同,所以原型的缺点就在属性全部共享,但是方法共享对象所需的。
构造函数的优缺点:
构造函数创建的对象,他们的属性根据输入的不同,各不相同,很适合项目所需,至于方法虽然都可以调用,但是所有对象重复调用同一个方法,浪费太多不必要的内存。
结合两者的优缺点组合成 →组合模式
function fn(name,age){
this.name=name; //利用构造函数的属性自定义: 解决了原型属性共享的问题
this.age=age;
}
fn.prototype.eat=function(){ //利用了原型的方法共享: 解决了构造函数的方法重复调用问题
console.log(this.name+"吃了反");
}
fn.prototype.old=function(){
console.log(this.age+"年龄");
}
var f1=new fn("李四",20);
f1.eat();
function fn(name,age){
this.name=name; //利用构造函数的属性自定义: 解决了原型属性共享的问题
this.age=age;
}
fn.prototype.eat=function(){ //利用了原型的方法共享: 解决了构造函数的方法重复调用问题
console.log(this.name+"吃了反");
}
fn.prototype.old=function(){
console.log(this.age+"年龄");
}
var f1=new fn("李四",20);
f1.eat();
1.5 动态模式
组合模式也并不是完美无缺,也有他的缺点:构造函数与原型分散,打破了面向对象的三大特征中的——封装;
function fn(name,age){
this.name=name;
this.age=age;
if(typeof this.eat!==function){
fn.prototype.eat=function(){
console.log(that.name+"吃了饭");
}
}
}
var f1=new fn("李四",20);
f1.eat(); //李四吃了饭
function fn(name,age){
this.name=name;
this.age=age;
if(typeof this.eat!==function){
fn.prototype.eat=function(){
console.log(that.name+"吃了饭");
}
}
}
var f1=new fn("李四",20);
f1.eat(); //李四吃了饭
其他:
-
Math.hypot( ):函数返回的是 所有参数的平方和的平方根。
Math.hypot(3,4); // 5 sqrt(3*3+5*5)=5
// 5 sqrt(3*3+5*5)=5
-
ES5 中的严格模式:"use strict"
如果直接调用一个函数,在严格模式下,this为undefined;在非严格模式下,this会指向window。