js圣杯模式,枚举,如何区分数组和对象,callee(代码学习)
程序员文章站
2023-11-12 18:39:52
1. 继承发展史(从a发展到d)
a 原型链继承:过多的继承没有用的属性
function grand(){this.grand='grand';this.name='h...
1. 继承发展史(从a发展到d)
a 原型链继承:过多的继承没有用的属性
function grand(){this.grand='grand';this.name='haha'} function father(){this.father='father'} function son(){this.son='son'} var grand = new grand(); father.prototype=grand; var father = new father(); son.prototype=father; var son = new son(); console.log(son.son,son.father,son.grand);//son father garnd 可以看出来形成了原型链,但是我可能不想要grand身上的name却也继承了
b 借用构造函数---不能借用构造函数的原型,每次都要多调用一次函数。降低效率
function father(){ this.address=123;this.familycount=3; } function son(){ father.call(this); //---> this.address=123;this.familycount=3;//重复 this.name='xiaoming' }
c 公有原型---明显的缺陷:修改子,会影响父
function father(){ this.familycount=3; } father.prototype.address=123; function son(){ this.name = 'xiaoming'; } son.prototype = father.prototype;//现在father和son的原型都是father.prototype那个房间里的东西,一动都变 var father = new father(); var son = new son(); console.log(son.address,father.address);//123 123 son.prototype.address = 234; console.log(son.address,father.address);//234 234 如果子搬出去住了,想改属性的值,或者给自己加了一个属性,父的也会变!!
d 圣杯模式---利用中间函数构造出的对象作为中间过度原型,产生原型链
function father(){ this.familycount=3; } function son(){ this.name = 'xiaoming'; } father.prototype.address='haha'; //封装一个继承函数 闭包的形式可以使f隐起来,不被访问到---闭包的私有化变量的使用方法 var inherit = (function(){ var f=function(){}; return function(target,source){ f.prototype = source.prototype;//将source的原型和f的原型变成同一个 target.prototype = new f(); //创建一个__proto__指向source.prototype的{},并让target构造出的对象都继承自这个{} //此时,修改target.prototype相当于是在这个空的{}中做修改,不会有任何影响 target.prototype.constuctor = target; //修改原型会导致原型失去自己构造函数的指向 target.prototype.uber = source.prototype;//超类:记录真正继承的的原型 }; })(); inherit(son,father); var son=new son(); console.log(son.address);//haha
2. 枚举---就是遍历
function person(name,age){ this.name=name; this.age=age; } person.prototype.secret='每个人都不一样'; var obj = new person('xiaozhang',24); for(var key in obj){ //过滤不是当前对象自己的属性 if(obj.hasownproperty(key)){ console.log(key+'是当前对象自己的','值是:'+obj[key]);//必须用obj[key],不能用obj.key //因为用.取属性会让系统自动转换为obj['key'],就是说系统默认点后就是字符串形式 }else{ //为false----会打印出原型链上所有人为设置的属性,系统自带的不会打印出来!! console.log(key+'是继承来的'); } } 'name' in obj;//true 'secret' in obj;//true in不论是当前对象里的还是原型链上的人为设置的属性都是返回true
3. a instanceof b----a对象的原型链上 有没有 b的原型 a对象是不是可以继承b的原型 a对象 是不是 由b函数构造出来的
例子---区分数组和对象:
var arr=[1,2],obj={}; //法一: 由谁构造的---可能会不靠谱,因为原型改变会导致构造函数也改变 console.log(arr.constructor,obj.constructor); //function array(){} function object(){} //法二: instanceof 原理差不多,原型链上有没有array console.log(arr instanceof array,obj instanceof array); //true false //法三: 调用object的tostring方法 console.log(object.prototype.tostring.call(arr),object.prototype.tostring.call(obj)); //[object array] [object object]
4. callee---属于arguments 的一个函数,就是自己
例子---立即执行函数没有名字,但是要写递归的时候:
var num=(function(n){ //没函数名 if(n==1){return 1} return n*arguments.callee(n-1);//这里回调自己 }(5)); console.log(num);//120
5. 写个小栗子---this
var foo = 123; function print(){ this.foo = 234; console.log(foo); } new print();//this是{}---> this.foo=234---> {foo:234}---> 打印的是foo,不是this.foo---> foo是个变量,请在作用域链上找,只有全局有个foo是123 print(); //this是window ---> window.foo = 234 ---> 所以foo从123变成了234