javascript---孔浩老师--昭通学院 20140902

/**************************************************************/

<a href="#" onclick="history.back()">返回</a>
 window.location.href=test01.html
window.open():
document.getElementById("wel").style.display = "none";
btn.onclick = function(event){
     event = event||window.event;
     alert(event.type);
     alert(this.value);
}
//先加载页面后加载方法
window.onload = init;
<body onload = init()></body>
funcion init(){  }

/**************************************************************/


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        var x = function(){
            alert("x");
            //对于函数而言,直接写return就等于有返回值
            return 100;
        };
        x();
        function fn() {

        }
        //此时是将y这个变量指向函数fn,可以通过y()来调用函数
        var y = fn;
        fun();
        //可以调用
        y();
        //将函数fn所执行的函数值传递给z变量,所以z为100
        var z = fun();
        alert(z);
        alert(y);
        function Person(name,age){
            //定义Person的属性
            this.name = name;
            this.age = age;
            //如果没有用this声明,这个变量就仅仅是一个局部变量,不是类的属性
            var x = 10;//局部变量,不能调用
            this.say = function(){
                alert(this.name+this.age);
            }
        }

        var p1 = new Person("zhangsan",12);
        alert(p1.name + p1.age);
        alert(p1 instanceof Person);
        p1.say();
        //可以通过对象的[]完成对属性的调用
        alert(p2["name"] +p2["address"]);
        //在js中对于对象而言,可以通过for in 来变量对象的属性
        for(var a in p1){
            //可以获取对象中所有显示声明的属性
            alert(a+":" + p1[a]);

        }

    </script>
</head>
<body>

</body>
</html>


/*****************************************************************/
//工厂方法创建Person对象

function createPerson(name,age){
            var  o = new Object();
            o.name = name;
            o.age = age;
            o.say =function(){
                alert(this.name + "," + this.age);
            }
            return o;
           
        }
        var p1 = createPerson("Leon",22);
        var p2 = createPerson("Ada",33);
        p1.say();
        p2.say();

//构造方法创建Person对象
function createPerson(name,age){
          
           this.name = name;
            this.age = age;
            this.say =function(){
                alert(this.name + "," + this.age);
            }
           
            
        }
        var p1 = new Person("Leon",22);
        var p2 = new Person("Ada",33);
        p1.say();
        p2.say();

//通过原型的方式构造

function Person() {
           
        }
        Person.prototype.name = "Leon";
        Person.prototype.age = 23;
        Person.prototype.say = function(){
            alert(this.name+","+this.age);
        }
 var p1 = new Person("Leon",22);
        var p2 = new Person("Ada",33);
        p1.say();
        p2.say();


  alert(Person.prototype.isPrototypeOf(p1));
  alert(p1.hasOwnProperty("name");
/*****************************************************************/
function Person() {

        }
 Person.prototype = {

          constructor:Person,//手动指定原型的constructor
            name:"Leon",
            age:123,
            say: function () {
                alert(this.name+","+this.age);
           }
  }
/*****************************************************************/
44---
  /**
         *基于原型的创建虽然可以有效的完成封装,但是依然有一些问题
         *1、无法通过构造函数设置属性值
         * 2、当属性中有引用类型变量值,可能存在变量值重复
         * */
        function Person() {

        }
        Person.prototype = {
            constructor:Person,
            name:"Leon",
            age:30,
            friends:["Ada","Chris"],
            say: function () {
                alert(this.name+"["+this.friends+"]");
            }
        }
        var p1 =  new Person();
        p1.name = "John";
        p1.say();//john[ada,chris]
        //会在原型中找friends,所以Mike是在原型中添加的
        p1.friends.push("Mike");
        var p2 = new Person();
        p2.say();//leon ada chris Mike

//-----------------------------------------------------------------------------------------------
/**
         *为了解决原型带来的问题,此处需要通过组合构造函数和原型来实现对象的创建
         * 这种属性在构造函数中定义,将方法在原型中定义
         * 这种有效集合了两种的优点,是目前最为常用的一种方式
         * */
        function Person(name,age,friends) {
            //属性在构造函数中定义
            this.name = name;
            this.age = age;
            this.friends = friends;
        }
        Person.prototype = {
            constructor:Person,
            //方法在原型中定义
            say: function () {
                alert(this.name+"["+this.friends+"]");
            }
        };
        //此时所有的属性都是保存在自己的属性中
        var p1 =  new Person("Leon",23,["Ada","Chris"]);
        p1.name = "John";
        p1.say();//john[ada,chris]
        //会在原型中找friends,所以Mike是在原型中添加的
        p1.friends.push("Mike");
        var p2 = new Person("Ada",33,["Leon"]);
        p2.say();//leon ada chris Mike

//-----------------------------------------------------------------------------------------------
44--
    /**
         * 动态原型
         *为了让定义的方式更符合java的需求,就把定义的原型代码放置到person这个构造函数中
         * */
        function Person(name,age,friends) {
            //属性在构造函数中定义
            this.name = name;
            this.age = age;
            this.friends = friends;
            if(!Person.prototype.say){
                alert("aaa");
                Person.prototype.say = function(){
                    alert(this.name+"["+this.friends+"]");
                }
            }
        }
      /*  Person.prototype = {
            constructor:Person,
            //方法在原型中定义
            say: function () {
                alert(this.name+"["+this.friends+"]");
            }
        };*/
        //此时所有的属性都是保存在自己的属性中
        var p1 =  new Person("Leon",23,["Ada","Chris"]);
        p1.name = "John";
        p1.say();//john[ada,chris]
        //会在原型中找friends,所以Mike是在原型中添加的
        p1.friends.push("Mike");
        var p2 = new Person("Ada",33,["Leon"]);
        p2.say();//leon ada chris Mike


/*****************************************************************/
45--继承
/**
         * js实现继承的第一种方式是基于原型的链的方式
         * */
        function Parent() {
            this.pv = "parent";

        }
        Parent.prototype.pp ="ok";
        Parent.prototype.showParentValue = function(){
            alert(this.pv);
        };
        function Child(){
            this.cv ="child";
        }
        /**
         * 让Child的原型链指向Parent对象,也就等于完成了一次继承
         * 注意内存模型
         */

        Child.prototype = new Parent();
        Child.prototype.showChildValue = function () {
            alert(this.cv);

        };
        var c = new Child();
        c.showParentValue();
        c.showChildValue();
        alert(c.pp);

//-----------------------------------------------------------------------------------------------
 /**
         * js实现继承的第一种方式是基于原型的链的方式
         * */
        function Parent() {
            this.pv = "parent";

        }
        Parent.prototype.pp ="ok";
        Parent.prototype.showParentValue = function(){
            alert(this.pv);
        };
        function Child(){
            this.cv ="child";
        }
        /**
         * 如果赋值之后,才进行原型链的设定,这样赋值的原型对象
         * 就会被重写掉,赋值的对象就不存在新的原型对象中
         */
        Child.prototype.showChildValue = function () {
            alert(this.cv);

        };
        /**
         * 让Child的原型链指向Parent对象,也就等于完成了一次继承
         * 注意内存模型
         */

        Child.prototype = new Parent();

        /**
         *当执行了下面这句话之后,意味着Child的原型又重写了
         * 这样就不存在任何的继承关系了
         * 使用原型链注意的第一个问题
         */
         Child.prototype = {
             showChildValue:function(){

             }
         };
        /**
         * 此时完成了对父类对象的重写
         */
        Child.prototype.showParentValue = function(){
          alert("override parent");
        };
        var c = new Child();
        c.showParentValue();
        c.showChildValue();
        alert(c.pp);
        /**
         * 在使用原型链进行继承后一定要注意的问题:
         * 1、不能在设定了原型链之后,再重新为原型链赋值
         * 2.一定在原型链赋值之后才能添加或者覆盖方法
         */
//-----------------------------------------------------------------------------------------------
/**
         * js实现继承的第一种方式是基于原型的链的方式
         * */
        function Parent() {
            this.pv = "parent";
            this.color = ["red","yellow"]

        }
        Parent.prototype.pp ="ok";
        Parent.prototype.showParentValue = function(){
            alert(this.pv);
        };
        function Child(){
            this.cv ="child";
        }
        /**
         * 使用原型链继承,最大的缺点是,无法从子类中调用父类的构造函数
         * 这样就没有办法吧子类中的属性赋值给父类
         * 第二个缺点就是,如果父类中有引用类型,此时这个引用类会添加到
         * 子类的 原型中,当第一个对象的修改了这个这个引用之后,其他对象
         * 同时修改
         * 所以一般不会单纯的使用原型链来继承
         */

        Child.prototype = new Parent();
        Child.prototype.showChildValue = function () {
            alert(this.cv);

        };


        /**
         * 此时完成了对父类对象的重写
         */
        Child.prototype.showParentValue = function(){
          alert("override parent");
        };

        var c1 = new Child();
        //Child中原型中color被修改
        c1.color.push("blue");
        alert(c1.color);

        var c2 = new Child();
        alert(c2.color);




/*****************************************************************/
46--基于伪装的继承方式
  function Parent() {

            this.color = ["red","yellow"];
            this.name = "leon";

        }

        function Child(){
            //在Child中的this明显应该是指向Child的对象
            //当调用Parent方法的时候,而且this又是指向了Child
            //此时就等于在这里完成了this.color = ["red","yellow"];
            //也就等于在Child中有了this.color属性,这样也就变相的完成了继承
            Parent.call(this);
            //这种调用方式,就仅仅完成了函数的调用,根本无法实现继承
           // Parent();
        }
        var c1 = new Child();
        c1.color.push("green");
        alert(c1.color);
        var c2 = new Child();
        alert(c2.color);

//-----------------------------------------------------------------------------------------------
   function Parent() {

            this.color = ["red","yellow"];
            this.name = "leon";
            this.say = function(){
                alert(this.name);
            }

        }
        /**
         * 由于使用伪造的方式,不会完成Child的原型指向parent
         * 所以say方法不存在,解决方法是,将这个方法放置到
         * Parent中使用this来创建,但是每个对象中又存在say
         * 这样空间占用太大,所以也不会单独的使用伪造的方式实现继承
         */
       /* Parent.prototype.say = function(){

        };*/

        function Child(){
            /**
             * 使用伪造的方式就可以把子类的构造函数参数传递到父类中
             */
            this.age = age;
            Parent.call(this,name);
        }
        var c1 = new Child("Leon",12);
        var c2 = new Child("Ada",22);
        c1.say();
        c2.say();


/*****************************************************************/
47--基于组合的方式实现继承
 /**
         * 组合的方式是属性通过伪造方法实现,方法通过原型链的方法实现
         */
        function Parent(name) {

            this.color = ["red","yellow"];
            this.name = name;
        }
        Parent.prototype.ps = function(){
          alert(this.name+","+this.age+"["+this.color+"]");
        };

        function Child(name,age){
            //已经完成了伪造
            Parent.call(this,name);
            this.age = age;
        }
        Child.prototype = new Parent();
        Child.prototype.say = function(){
          alert(this.name+","+this.age+"["+this.color+"]");
        };

        var c1 = new Child("Leon",12);
        c1.color.push("blue");
        var c2 = new Child("Ada",22);
        c1.say();
        c1.ps();
        c2.say();
        c2.ps();


/*****************************************************************/
48--函数调用的作用域链

 <script type="text/javascript">
        fn1();
        //不会报错,对于通过function fn()这种写法来定义的函数,永远都会被最先初始化
        function fn1(){
            alert("fn1");
        }
       // fn2();
        /**
         * 使用如下方式定义函数,不会被先执行,如果在之前调用该函数就会报错
         *
         * 以下函数的定义方式是先在内存中创建了一块区域,之后通过一个fn2的变量
         * 指向这块区域,这块区域的函数开始时没有名称的,这种函数就叫做匿名函数
         */
        var fn2 = function(){
            alert("fn2");

        };
        /**
         * 在js中当进行函数的调用,会为每一个函数增加一个属性scope,通过这个属性
         * 来指向一块内存。这块内存中包含的所有的上下文使用的变量,当在某个函数中调用了
         * 新函数之后,新函数依然会有一个作用域来执行原有的函数的scope和自己新增的
         * scope,这样就形成了一个链式结构。
         * 这就是js的一个作用域链
         */

        var color = "red";
        var showColor = function(){
            alert(this.color);
        };
        function changeColor(){
            var anotherColor = "blue";
            function swapColor(){
                var tempColor = anotherColor;
                anotherColor = color;
                color = tempColor;
            }
            swapColor();

        }
        changeColor();
        showColor();

    </script>


/*****************************************************************/
48--闭包
  <script type="text/javascript">
        /**
         * 通过以下操作带来的最大的好处是,compareObjectFunction的作用域变大了
         * 当compareObjectFunction结束之后,prop这个变量依然存在
         */

        function compareObjectFunction(prop){
            //匿名函数
            return function(obj1,obj2){
                if(obj1[prop]>obj2[prop])return 1;
                else if(obj1[prop]<obj2[prop])return -1;
                else return 0;
            }
        }
        var o1 = {name:"leon",age:23};
        var o2 = {name:"Ada",age:28};
        //此时就是基于name来进行比较
        /**
         * 在java或者C++中,以下代码执行完成之后,需要进行内存的释放
         * 此时对于java和C++这些静态语言而言,prop会被释放
         * 但是在js中, 这个作用域却被放大了
         */
        var compare = compareObjectFunction("age");
        //此时就比较了o1和o2
        /**
         * 在js中,prop在这里依然可以被访问,这种通过返回函数来扩大函数的作用域的方法
         * 就是闭包
         */
        var rel = compare(o1,o2);
        alert(rel);


    </script>

/*****************************************************************/
49--闭包--作用域链
<script type="text/javascript">
        function fn1(){
            //创建了一个数组
            var fns = new Array();
            //i这个变量是保存在fn1这个作用域中的
            for(var i=0;i<10;i++){
                //(2)num这个变量保存在fns这个tf这个作用域,每一个闭包的num都是不一样
                //所以此时所消耗的内存特别大
                var tf = function(num){
                    fns[num] = function(){
                        return num;
                    }
                };
                tf(i);
               /*(1) //数组中括号的只是一组函数
                fns[i] = function(){
                    return i;

                }*/
            }
            return fns;
        }
        var fs = fn1();
        for(var i=0;i<fs.length;i++){
            //(1)此时通过闭包来调用所有函数,当输出i的时候会去上一级的作用域中查找
            //这个时候i的值已经是10,所以连续输出了10个10
            //(2)每一个fs都是在不同的作用域链中,num也是保存在不同的作用域中,输出0-9
            document.write(fs[i]()+"<br/>");
        }


    </script>
//-----------------------------------------------------------------------------------------------
<script type="text/javascript">
      var name = "window";
        var person = {
            name:"zhangsan",
            age:23,
            say:function(){
                return function () {
                    return this.name;
                }
            }
        };
        /**
         * 当完成person.say()之后,这个函数就调用结束了,在这个函数调用结束之前
         * this是指向person,但是在调用匿名函数的时候,this就指向window了,所以
         * 得到的结果是window
         */
       alert( person.say()());


    </script>
//-----------------------------------------------------------------------------------------------
<script type="text/javascript">
        var name = "window";
        var person = {
            name:"zhangsan",
            age:23,
            say:function(){
                //that指向perosn
                var that = this;
                return function () {
                    return that.name;
                }
            }
        };
        /**
         * 此时that是指向person的,所以调用that.name就是person中
         * name
         */
       alert( person.say()());


    </script>


/*****************************************************************/
50--块作用域
 <script type="text/javascript">
        for(var i=0;i<10;i++){

        }
        //在js中没有块作用域,不管使用循环还是判断之后,这个变量会一直存在
        /**
         * 所以当在全局使用某个变量进行循环或者判断之后,这个变量可能会影响
         * 到函数中的变量,所以在特殊情况下不要使用全局变量,而且使用全局变量
         * 在作用域链的嘴上层,访问时最慢的
         */
        var i; //此时会认为是无效语句,除非使用var i=0;
        alert(i);

    </script>
/*匿名函数*/
<script type="text/javascript">
        /**
         * 在一个团队进行开发时,可能会涉及到定义同名的全局变量,所以在开发中
         * 一定养成如下习惯,将全局变量的代码放到一个匿名函数,并且马上调用
         * 匿名函数,这样也可以执行全局变量的代码,但是这些变量被控制在开发人员
         * 想要控制的作用域中了
         */
        (function(){
            for(var i=0;i<10;i++){

            }

        })();

        function fn(){
            alert(i);
        }
        fn();

    </script>
<script type="text/javascript">
        function Person(name) {
            /**
             *此时就没有办法直接访问name这个属性,因为没有this.name
             * 要访问name只能通过this.getName,this.setName
             * 但是使用这种方式创建私有变量带来的问题是,每个对象都存储
             * 了大量的函数,解决的办法是通过静态私有变量来解决
             */
            this.setName = function(value){
                name = value;
            };
            this.getName = function(){
                return name;
            };

        }
        var p = new Person("aa");
        alert(p.getName());
        p.setName("bb");
        alert(p.getName());

    </script>
<script type="text/javascript">
        var Person;
        (function(){
            //name在函数结束之后就消失,外面无法引用
            var name = "";
            Person = function(value){
                name = value;
            };
            Person.prototype.setName = function(value){
                name = value;
            };
            Person.prototype.getName = function(){
                return name;
            };
        })();

        var p1 = new Person("aa");
        p1.setName("bb");
        alert(p1.getName());

    </script>

/*****************************************************************/
51--原型扩展
<script type="text/javascript">
        /**
         * 以下为String扩展了trim的方法去除空格
         */
        String.prototype.trim = function(){
            //js的正则表达式和Java很类似,区别是js是用//
           return this.replace(/(^\s+)|(\s+$)/g,"");

        };
        var str = "   aaaa     ";
        alert("|" +str.trim() + "|");

    </script>
/*****************************************************************/

 

posted @ 2020-02-29 12:19  my_flash  阅读(72)  评论(0)    收藏  举报