var f=new Object( );
除null之外所有的对象都有_ _proto__属性,这个属性指向当前对象的内部原型对象。
见笔记 js对象
构造函数的原型,构造函数都有_ proto_
所有函数的原型的_ _proto__都指向Object.prototype(除掉Function)
构造函数的原型上的_ _proto__指向Object.prototype
Object的原型上的_ _proto__指向null
构造函数上的_ _proto__指向Function.prototype(这是一个空函数)
Function原型上的_ _proto__指向Object.prototype
Function.prototype是所有函数的根
Object对象的_ _proto__属性指向Function.prototype
闭包引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
闭包是一个函数和函数所声明的词法环境的结合。
<script>
function f1(x)
{
var tmp=3;
return function(y)
{
console.log(x+y+tmp);
}
}
//调用f1方法,并把匿名函数返回给bar
//bar中有f1函数的x变量 tmp变量 匿名函数
//f1函数执行完成 tmp和x也不会释放
var bar=f1(5); //此时bar指向匿名函数。bar是一个闭包。
bar(10);
</script>
1. 匿名自执行函数(匿名函数模拟块级作用域)
注意,尽量少定义全局变量。
;(function (a)
{
var m=10; //这里定义的变量只能在函数体内使用
console.log(a);
})(6); //立即执行
//也可以这样写,但是不推荐
;(function(a)
{
console.log(a);
}(5))
;(匿名函数)(传入的参数)
2.循环注册dom事件
var aLi=document.getElementsByTagName("li");
for(var i=0;i<aLi.length;i++)
{
aLi[i].onclick=function()
{
console.log(i); //因为循环事件先发生,所以打印的结果都是5
}
}
//利用闭包解决
for(var i=0;i<aLi.length;i++)
{
;(function (a){
aLi[a].onclick=function()
{
console.log(a);
}
})(i); //将i作为参数传入到自执行的函数中 0-4,传的参数是值的赋值
}
3.定时器中闭包的应用
//利用闭包解决问题
for(var i=0;i<5;i++)
{
(function(a)
{
setTimeout(function(){
console.log(a);
},1000*a)
})(i); //i只传入了0-4
}
//利用let解决问题
for(var i=0;i<5;i++)
{
let k=i;
setTimeout(function()
{
console.log(k);
},1000*k);
}
//方法1
function creat()
{
var age=0;
this.getAge=function()
{
return age;
}
this.setAge=function(a)
{
age=a;
}
}
var p=new creat();
p.setAge(10);
console.log(p.getAge());
//方法2
function creat2()
{
var age=0;
return{
getAge:function()
{
return age;
},
setAge:function(a)
{
age=a;
}
}
}
var p2=creat2();
p2.setAge(20);
console.log(p2.getAge());
function CreatCat(age,name)
{
var a=new Object();
a.name=name;
a.age=age;
a.run=function()
{
console("cat is running");
}
return a;
}
var cat=CreatCat(10,'pink');
cat instanceof CreatCat; //false
cat instanceof Object; //true
工厂模式是标准化的生成默认对象的函数
优点:
缺点:
function CreatCat()
{
this.age=10;
this.name='cat';
this.run-function()
{
console.log("is running");
}
}
var cat1=new CreatCat();
var cat2=new CreatCat();
cat1.age=20;
console.log(cat1.age);
console.log(cat2.age);
cat1 instanceof CreatCat; //true
cat1 instanceof Object; //true
当使用new来调用构造函数的时候经历了以下过程
优点:
缺点:
利用prototype给原型添加属性和方法。
组合使用构造函数模式与原型模式
公共的属性和方法放到 原型上,独有的属性使用构造函数模式,放到对象自己身上。
优点:
function CreatCat()
{
this.age=10;
this.name='cat';
}
CreatCat.prototype.run=function()
{
console.log("is running");
}
var cat1=new CreatCat();
function CreatCat()
{
var a=new Object;
a.name='qwe';
a.age=18;
a.run=function()
{
console.log('run');
}
return a;
}
var c1=new CreatCat();
var c2=CreatCat();
可以用new创建也可以不用new创建。
function Animal(age,name)
{
this.go=function()
{
console.log('go running');
}
}
Animal.prototype.run=function()
{
console.log('is running');
}
function Cat(age,name) //Cat和Animal有同样的属性
{
this.age=age;
this.name=name;
}
//原型继承的方法
Cat.prototype=new Animal(); //将animal的属性以及原型上的属性继承给cat的原型
Cat.prototype.constructor=Cat; //因为前面的代码cat原型上的constructor会指向animal,这里把它还原
var c1=new Cat(10,'luck');
c1.go(); //调用了Animal上的方法
c1.run(); //调用了Animal.prototype上的方法
缺点:
function Animal(age,name)
{
this.age=age;
this.name=name;
this.go=function()
{
console.log('go running');
}
}
Animal.prototype.run=function()
{
console.log('is running');
}
function Cat(age,name) //Cat和Animal有同样的属性
{
//第一次执行父类的构造函数
Animal.call(this,age,name); //将animal的this指向为cat的this
}
//第二次执行父类的构造函数
Cat.prototype=new Animal();
Cat.prototype.constructor=Cat;
var c1=new Cat(12,'qw');
console.log(c1.age);
原型式继承是避免调用父类构造函数的一种巧妙的方式。本质就是借用对象来构造另外一个对象。
缺点:
function object(o)
{
function F(){};
F.prototype=o;
return new F();
}
var m={age:12,name:'qwe'};
var m1=object(m); //使空函数的prototype==m并把空函数返回给m1
var m2=Object.create(m); //和上面一样,ECMAScript6中已经将上面的方法封装成create
console.log(m2.age);
console.log(m1.age);
function object(o)
{
function F(){};
F.prototype=O;
return new F();
}
function cat (c)
{
var p=object(c);
p.say=function()
{
console.log('hi');
}
return p;
}
function Animal(age,name)
{
this.name=name;
this.age=age;
}
Animal.prototype.run=function()
{
console.log('is running');
}
function Cat(age,name)
{
Animal.call(this,age,name); //将this,age,name指向animal
}
function inheritFrom(o) //寄生继承
{
var t=Object.create(o);
t.constructor=Cat;
return t;
}
Cat.prototype=inheritFrom(Animal.prototype); //寄生继承
var cat=new Cat(10,'lucy'); //组合继承
cat.run();
console.log(cat.age);