js 杂项

  1. Arguments对象有一个callee属性,标示了当前Arguments对象所在的方法。
    可以使用它来实现匿名函数的内部递归调用。修改Arguments对象的length属性并不会改变它的长度。
    function(x) {     
        if (x <= 1) return 1;     
        return x * arguments.callee(x-1);     
    }
  2. 每一个函数都包含了一个prototype(原型)属性,这个属性构成了javascript面向对象的核心基础
  3. 使用new运算符调用构造函数时,在执行第一行代码前先创建一个对象,只有this才能访问这个对象,将新的空对象设置为该函数中“this”的值。 默认情况下该对象是构造函数的返回值,不必明确使用return。
  4. 在javascript中,每个对象都有一个prototype属性,这个属性指向了一个prototype对象。"原型对象"和"原型属性"是两个不同的概念。当创建了空对象后,new会接着操作刚生成的这个对象的prototype属性。
    每个方法都有一个prototype属性(因为方法本身也是对象)。new操作符生成的新对象的prototype属性值和构造方法的prototype属性值是一致的。构造方法的prototype属性指向了一个prototype对象,这个prototype对象初始只有一个属性constructor(这是Object的prototype),而这个constructor属性又指向了prototype属性所在的方法。

    当用构造函数创建一个新的对象时,它会获取构造函数的prototype属性所指向的prototype对象的所有属性。对构造函数对应的 prototype对象所做的任何操作都会反应到它所生成的对象身上,所有的这些对象共享构造函数对应的prototype对象的属性。


  5. 用prototype模拟继承
    function Circle(radius) {  //定义父类Circle     
        this.radius = radius;     
    }     
    Circle.prototype.area = function() { //定义父类的方法area计算面积     
        return this.radius * this.radius * 3.14;     
    }     
        
    function PositionCircle(x,y,radius) { //定义类PositionCircle     
        this.x = x;                    //属性横坐标     
        this.y = y;                    //属性纵坐标     
        Circle.call(this,radius);      //调用父类的方法,设置PositionCircle类的radius属性   相当于super()  
    
    
    
    }     
    PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类,将Circle中的所有属性,包括prototype都继承都PositionCircle中。
        
    var pc = new PositionCircle(1,2,1);     
    alert(pc.area());  //3.14     
                       //PositionCircle类的area方法继承自Circle类,而Circle类的     
                       //area方法又继承自它的prototype属性对应的prototype对象     
    alert(pc.radius); //1  PositionCircle类的radius属性继承自Circle类     
        
    /*   
    注意:在前面我们设置PositionCircle类的prototype属性指向了一个Circle对象,   
    因此pc的prototype属性继承了Circle对象的prototype属性,而Circle对象的constructor属   
    性(即Circle对象对应的prototype对象的constructor属性)是指向Circle的,所以此处弹出   
    的是Circ.   
    */    
    alert(pc.constructor); //Circle         
        
    /*为此,我们在设计好了类的继承关系后,还要设置子类的constructor属性,否则它会指向父类   
    的constructor属性   
    */    
    PositionCircle.prototype.constructor = PositionCircle     
    alert(pc.constructor);  //PositionCircle 
     
  6. 返回函数的函数就是个典型的闭包,函数中的变量不能被外界修改,只能通过调用返回的函数(定义在函数内部的函数)进行修改
    function temp() {     
        var i = 0;     
        function b() {     
            return ++i;     
        }     
        return b;     
    }     
    var getNext = temp();     
    alert(getNext());    //1     
    alert(getNext());    //2
     
  7. 作用域链
    在javascript解释器启动时,会首先创建一个全局的对象(global object),也就是"window"所引用的对象。然后我们定义的所有全局属性和方法等都会成为这个对象的属性。不同的函数和变量的作用域是不同的,,因而构成了一个作用域链(scope chain)。很显然,在javascript解释器启动时,这个作用域链只有一个对象:window(Window Object,即global object).
    在上面的闭包示例中,由于temp函数是一个全局函数,temp()函数的作用域(scopr)对应的作用域链就是js解释器启动时的作用域链,只有一个window对象。当temp执行时 ,首先创建一个call object(活动对象),然后把这个call object添加到temp函数对应的作用域链的最前面,这时,temp()函数对应的作用域链就包含了两个对象:window对象和temp函数对应的call object,temp函数中的变量i、函数b()都会成为call object的属性。
    js的函数是词法性的:函数是运行在定义他们的作用域中(b函数运行在temp函数的作用域中,因此可以引用到temp作用域中定义的变量),而不是调用他们的作用域中。 只要b函数被定义在temp中,b就可以访问temp函数定义的所有变量,即使temp函数已经执行完毕

    而在函数b的作用域链中,b对应的call object中却没有变量i,只有argments属性,这是因为变量i不是在函数b中定义的(没有使用var来声明),只有用var 关键字声明的属性才会添加到对应的call object上。在函数执行时,首先查找对应的call object有没有需要的属性,如果没有,再往上一级查找,直到找到为止,如果找不到,那就是undefined了.
  8. 用闭包模拟私有变量
    function Person(name, age) {       
        this.getName = function() { return name; };       
        this.setName = function(newName) { name = newName; };       
        this.getAge = function() { return age; };       
        this.setAge = function(newAge) { age = newAge; };       
    }       
           
    var p1 = new Person("sdcyst",3);       
    alert(p1.getName());  //sdcyst       
    alert(p1.name);       //undefined   因为Person类没有name属性       
    p1.name = "mypara"    //显示的给p1添加name属性       
    alert(p1.getName());  //sdcyst     但是并不会改变getName方法的返回值       
    alert(p1.name);       //mypara     显示出p1对象的name属性       
    p1.setName("sss");    //改变私有的"name"属性     
    alert(p1.getName());  //sss       
    alert(p1.name);       //仍旧为mypara
     

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值