js继续(暑假2)

习题2:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<script type = "text/javascript">
    a = 100;
    function demo(e){
        function e(){}
        arguments[0] = 2;          // 更改实参的值
        document.write(e);
        if(a){
            var b = 123;                 //不执行里面
            function c(){

            }
        }
        var c;
        a = 10;
        var a;
        document.write(b);
        f = 123;                           //直接赋值,被放在GO中
        document.write(c);
        document.write(a);
    }
    var a;
    demo(1);
    document.write(a);
    document.write(f);
</script>
</body>
</html>

习题3:
题目在闭包精细版里的1小时52分钟处(就是求字节数)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<script type="text/javascript">
    function retByteslen(target) {
        var count,
             len;
             count = len = target.length;
        for(var i = 0; i < len; i ++){                //进行了优化 ,不用每次都计算target.length 将这个值保存出来赋给len
            if(target.charCodeAt(i) >= 255){   //进行了优化,不用进行多次比较,只进行了一次比较,因为 不管是中文还是英文,都先加一,判断中文个数在进行再次加一
                count ++;
            }
        }
        console.log(count);

    }
</script>
</body>
</html>

习题4:

逗号运算符:若是逗号前面是表达式,就计算前面的,然后,若是逗号后面是表达式,就计算后面的表达式,都计算完了,将后面表达式的值返回。
var a = (1 - 1, 1 + 1);      // a = 2
例1:
    var f = (
            function f(){
                return "1";
            },
            function g(){
                return 2;
            }
    )();
    console.log(typeof f);        //结果为number

习题5:

//所有变量未经声明就使用肯定报错,唯一一个 不报错的就是放在typeof中 并且返回undefined
    var x = 1;
    if(function f(){}){     f当完条件之后对自己产生变化,一个括号将函数圈在里面,无论括号里面是不是将它当作条件,无论内部如何执行,他依然是括号,是括号就要将里面的东西变为表达式,将它变成表达式它就不是函数定义了,f就消失了
        x += typeof f;   //未经声明的变量只有放在typeof操作符中才不报错,返回undefined(字符串类型)
    }
    console.log(x);      //若是1加上非字符串类型的undefined得到的结果为非数NaN,此题结果为1undefined
56.对象
1.用已学的知识点,描述一下你心目中的对象。
例1:(包含了四个属性两个方法)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<script type="text/javascript">
    var mrDeng = {
        name : "mrDeng",                           //属性
        age : 40,                                          //属性
        sex : "male",                                    //属性
        health : 100,                                    //属性
        smoke : function (){                        //方法
            console.log('I am smoking');
            this.health --;                              // 等价于 mrDeng.health --
        },
        drink : function (){                                    //方法
          console.log('I am drinking');
            this.health ++;                            //等价于 mrDeng.health ++;
        }
        marry : function(someone){
            this.wife = someone;      
        },
    }
    delete mrDeng.name                          //删除
</script>
</body>
</html>

调用时: 
mrDeng.smoke() 这是调用函数,使用方法,并且返回undefined ,如果没写return,控制台就返回undefined
mrDeng.smoke 这是函数体引用 不改变什么
2.属性的增、删、改、查
(1)增加:mrDeng.wife = "小刘"       //可以写入console.log中,也可以直接写在控制台中,但是不用document.write
(2)查:如上问中,就是查询、
(3)删:delete mrDeng.name           //再访问时结果为undefined
3.对象的创建方法
(1)var obj = {}   plainObject   对象字面量/对象直接量
(2)构造函数(结构上和函数没有任何分别)
      a.系统自带的构造函数 new Object()(执行一次生产一个对象,并且每个对象都是一模一样的,且相互独立的)可以通过var obj = new Object();通过它能产生一个真真切切的对象
      b.自定义
    例1:
    function Person(){

    }
    var person = new Person();       //有new就能生成对象
    例2:
    function Car(){                            //就是一个函数,所以冒号什么的,逗号什么的都不用写,它就是一个函数! 在外部进行更改时属性也只能通过=号
        this.name = "BMW";              //双引号?
        this.height = "1400";
        this.length = "4900";
        this.health = 100;
        this.run = function (){              //只能用this,不能用名字进行区分,因为刚生产时都是一样的没有什么区别,
            this.health --;
        }
    }
    var car1 = new Car();
    var car2 = new Car();
    car1.name = "sjska";
    car2.name = "fjakwigo";
   例3:
    function Car(color){        //参数才能使函数发生变化,才能变成自定义环节
        this.color = color;
        this.name = "BMW";
        this.height = "1400";
        this.length = "4900";
        this.health = 100;
        this.run = function (){
            this.health --;
        }
    }
    var car1 = new Car('green');
    var car2 = new Car('red');
    car1.name = "sjska";
    car2.name = "fjakwigo";
javascript中对象是非常灵活的 可以通过增删改查,但是java c++只要定义了对象 那么这个对象就是固定的不能改变,
在外部通过增加属性的方式来增加一个方法的话,只能通过=号,不能写冒号: ,在对象内部大括号中写冒号: ,
构造函数就这一个特点:大驼峰式命名规则:TheFirstName
小驼峰式命名规则:theFirstName

57.构造函数内部原理
构造函数必须加new,本来就是一个函数但是加上new就能实现构造函数的原理
1.在函数体最前面隐式的加上this = {}
2.执行 this.xxx = xxx;
3.隐式的返回this
例1:
    function Student(name,age,sex){
        //第一步在逻辑的最顶端生成隐式的var this = {}
        //第二步就是AO { this :{name  : 'xiaoliu'}};
/*        var this = {
            name : ""
            age:.....
        };*/
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.grade = 2016;
        //第三步return this;
    }
    var student = new Student('xiaoliu',1324,'male');
例2:
    function Person(name,height) {
        //var this = {}
        this.name = name;
        this.height = height;
        this.say = function () {
            console.log(this.say);
        }
        //return this
    }
    console.log(new Person('xiaoliu',180).name);
例3:
    function Person(name,height) {
        //var this = {}
        this.name = name;
        this.height = height;
        this.say = function () {
            console.log(this.say);
        }
        //return {};                                 //结果返回空对象
        //return 142;                             //返回原始值则不影响结果,其他的会影响结果
    }
    console.log(new Person('xiaoliu',180).name);    //有new就不可能返回原始值
例4:模拟构造函数过程,可以执行但是不这么用,因为还有深层次的东西无法模拟
    function Person (name , age){
        var that = {};
        that.name = name;
        that.age = age;
        return that
    }
    var person1 = new Person ('xiaoliu' , 20);
    var person2 = new Person ('xiaowang' , 30);

58.包装
原始值是坚决不能有自己的属性与方法的,它是独立的值,对象可以有,
数字类型对象:    var num = new Number(123);
字符串类型对象:    var str = new String('fafa');
布尔类型对象:    var bol = new Boolean(true);
null undefined不可以拥有属性,会报错
例1:注释部分就是包装类
    var str = 'abcd';
    str.length = 2;
        //new String('abcd').length = 2; delete

        //new String('abcd').length = 4 字符串类型对象本身就有length属性
    console.log(str.length);               //4

        //new String('abcd').length = 2; delete 该截断还是会截断的,不过和真正的str没有任何关系

    console.log(str);                          // abcd
例2:
    var num = 4;
    num.len = 2;
        //new Number(4).len = 2 ;delete

        //new Number(4).len 这个Number与上一个Number不是一个 这个里面没有len属性所以返回undefined
    console.log(num.len);                 //undefined
对象包装类下 30分开始往后都是例题

1.
    var str = "abc";
    str += 1;                                          //str = abc1
    var test = typeof(str);                     //字符串 String
    if(test.length == 6){
        test.sign = "typeof的返回结果可能为String"     //包装的过程 赋完值就销毁
    }                                                        //新生成 new String(String).sign   ,什么也没有
    console.log(test.sign);                     //输出结果undefined

2.
    function Person(name,age,sex){
        var a = 0;                                  //保存到了AO中
        this.name = name;
        this.age = age;
        this.sex = sex;
        function sss(){                             //产生了闭包
            a ++;
            document.write(a);
        }
        this.say = sss;
    }
    var oPerson = new Person();
    oPerson.say();                                 //调用函数,方
法,a+1
    oPerson.say();                                 //更改同一个变量a的值,a再加1
    var oPerson1 = new Person();        //新生成一个对象,和别的对象彼此独立
    oPerson1.say();                                //a从0开始++
                                                             //结果为1 2 1
备注:alert 弹出框 ,用法:alert('我是小美女');

59.原型
1.原型是function对象的一个属性,它定义了构造函数制造出的对象的公有祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
例1:
    Person.prototype.name = "呵呵";
    function Person(){
                     
    }
    var person = new Person();                  //person.name = 呵呵,自己本身没有name属性,但是自己祖先有,可以直接拿过来用,这样描述的就是一种继承
    var person1 = new Person();                //与person共有一个祖先,Person.prototype有什么属性,它俩就有什么属性
例2:
    Person.prototype.name = "呵呵";
    function Person(){ 
        this.name = "哈哈哈";                         //自己身上有属性的话取自己的,可近的来,没有的话去父亲那里找
    }
    var person = new Person();                  
    var person1 = new Person();
例3:
    Person.prototype.name = "呵呵";
    Person.prototype.say = function(){
        console.log('啦啦啦');
    }
    function Person(){
        
    }
    var person = new Person();                       //这些对象身上没有属性和方法,它用的是它原型上的,是一种借用,是一种继承关系,并不属于真正的自己
    var person1 = new Person();
2.利用原型特点和概念,可以提取共有属性
例1:
    Car.prototype.height = 1400;                      //共有属性,避免冗余
    Car.prototype.lang = 4900;
    Car.prototype.carName = "BMW";
    function Car(color,owner){
        this.color = color;
        this.owner = owner;
    }
    var car = new Car('red','LFY');
    var car1 = new Car('green','LFF');
3.对象属性上增删和原型属性上增删改查
例1:
    Person.prototype.lastName = "LFY";
    function Person(name){                                  
        this.name = name;
    }
    var person = new Person('xiaoming');   
改:在控制台更改person.lastName时,只是更改了自己的属性值。自己的属性值增加了lastName,调用时也是从自己属性中调用,但是原型并没有改变,要更改原型,只有使用Person.prototype.lastName 才能更改原型,其实使用person.lastName时不叫更改属性,这叫往自己里添加属性,但是要是没有的话 会在原型里找
增:改都不可能,更不能增了,后代是不可能修改原型里的值的
删:在控制台打出delete person.abc 结果为true,因为删除一个本来就不存在的东西当然可以,所以显示true,同理所以delete person.lastName结果显示true,但是person.lastName的值还是存在并没有删掉
例2:
    Person.prototype.lastName = "LFY";
    function Person(name){
        this.name = name;
    }
    var person = new Person('xiaoming');
例3:原型的另一种写法,既然它是对象,那就可以按对象那么写
    Car.prototype = {
        height :1400,
        lang : 4900,
        carName : "BMW"
    }
    function Car(){

    }
    var car = new Car(); 

4.对象如何查看原型,隐式属性-__proto__:
例1:
在我们用new生成新对象时,三段式:生成空对象,this,返回
但是在这里就第一步有区别,刚开始这个对象并不是空的,里面上来就有东西,里面的东西就是一个属性,放的就是如下:
        var this = {
          __proto__ : Person.prototype             //当你访问这个对象的属性时,这个对象身上如果没有这个属性的话它就会通过__proto__属性指向的索引去找Person.prototype身上有没有自己想要的属性,相当于一个连接的关系把原型和自己连接到一起了
        };
 __proto__里面存的是这个对象的原型,每个对象都有一个 __proto__属性指向它的原型。
例2:
    Person.prototype.name = "LFG"
    function Person(){

    }
    var obj = {                                                 //将对象的原型指向它,当调用person.name时访问的是obj而不是Person.prototype.name
        name : 'LYY',
    }
    var person = new Person();
    person.__proto__ = obj;                             //将指向的原型进行更改
例3:(1)
    Person.prototype.name = "abc";
    function Person(){

    }
    var person = new Person()
    Person.prototype.name = "sunny";                 //person.name = "sunny"   补充:这个里面改变的是属性,是房间里的东西,但是房间没变,结果为sunny
         (2)
    Person.prototype.name = "abc";
    function Person(){

    }
    Person.prototype.name = "sunny";                 //这条语句放在放在new语句之前之后没什么分别,但是下面的两道例题就不一样了,这个改变的是房间里的东西,并没有改变房间,而下面的一道例题,最后改变了房间,所以__proto__会指向new(生成对象)之前的房间
    var person = new Person()

例4
    Person.prototype.name = "abc";
    function Person(){
        //     var this = {
        //   __proto__ : Person.prototype                //__proto__指向的是原来的的值,Person.prototype再后面已经更改了值
        //}
    }
    var person = new Person()
    Person.prototype = {                                      //person.name = "abc",因为这个Person.prototype已经不是上面那个__proto__指向的Person.prototype了,这个是新的
        name : "sunny"                                            //补充:这个直接改变的是房间,不是属性,所以不同,而且,在对象生成完才更改的房间,已经不起作用了,因为对象已经生成完了,引用已经确定了
    }
例5:
    Person.prototype.name = "abc";
    function Person(){                                           //考虑预编译环节,将函数声明提升到最前面,只有在new后才会生成对象,所以在最后的位置上才生成对象,而中间出现的后一个的更改会将前面的值覆盖掉。上一个题不一样,例4在生成对象之后才进行的更改房间,已经晚了,对象已经生成完了,__proto__已经指向之前的房间了。而这个题,在生成对象之前并且__proto__并没有指向任何房间时进行更改,后面的值当然会覆盖掉之前的值
     /*   var this = {
            __proto__ : Person.prototype
        }*/
    }
    Person.prototype = {
        name : "sunny"
    }
    var person = new Person();
5.对象如何查看对象的构造函数
例1:
    Car.prototype.name = 123;
    function Car(){

    }
    var car = new Car();

//在控制台打出car.constructor就能找到对象的构造函数,这是Car.prototype自带属性,是隐式的,是浅粉色的,要是主动在Car.prototype中添加属性,就是显式属性,是紫色的
例2:constructor虽然是系统隐式给的,但是可以手动更改
    function Person(){
        
    }
    Car.prototype = {
        constructor : Person,                 //更改后car.constructor就变为了Person,car找错了父亲
    }

    function Car(){

    }
    var car = new Car();
6.总结:就是原型为Car.prototype,它是一个对象,里面有constructor和__proto__属性,用法是car.constructor可以找到对象car的构造函数,car.__prpto__可以找到对象的的原型,它是在构造函数第一步的this中的,car.__proto__指向的是Car.prototype,每个对象都有一个__proto__属性指向自己的原型,Car.prototype中也有这个属性,不过指的是Car.prototype这个对象的原型,还有默认person.__proto__ 指向Person.prototype
问题:
    var a = {
        name : "1z",
    }
    var b = a;
    var a = {
        name : "b",         //因为这个不是在原有基础上进行改变,而是重新开始了一个新对象和之前的就没有关系了,要是在原有基础上进行更改,那么一个变,另一个也变,因为是引用值
    }
 

60.原型链:把原型上面再一个原型,再加一个原型,再加一个原型,这样的一个方法,把原型连成链,依照链的顺序,像作用域链一样的访问的一个东西,叫做原型链,原型链的连接点就是__proto__,原型链的访问顺序和作用域链的访问顺序是一样的,差不多,都是可近的来,近的往远的进行排查,近的有,就用近的,近的没有就往远了找
1.Object.prototype是所有对象的最终原形
例1:
    Grand.prototype.Lastname  = "Deng";           //   Grandl.prototype.__proto__ = Object.prototype; Object.prototype是所有对象的最终原形,里面就没有__proto__属性了,因为没有原型了
    function Grand (){

    }
    var grand = new Grand();
    Father.prototype = grand;
    function Father(){
        this.name = "xuming";
    }
    var father = new Father();
    Son.prototype = father;
    function Son(){
        this.hobbit = "smoke";
    }
    var son = new Son();
2.原型链属性的增删改查(基本上与原型是一致的)
查;查看属性就是可近的来,近的没有就往远了找,一直找到终端,终端都没有就undefined
删:原型链上的属性通过子孙是不可以删的,通过自己可以删
改:不能说子孙完全不能修改这个父亲的属性
例1:
  还是上面那个代码 
  在控制台写son. fortune.card2 = "hahha",然后父亲构造函数中的fortune就有card1和card2两个属性
  因为这种修改是引用值自己的修改,因为他是引用值,引用值自己给自己加属性是可以的,这不算赋值的修改,这算一种调用的修改,这种修改是可以的,但是直接加值,覆盖型的修改是不行的,.card2这种修改只限于引用值的修改,原始值是不行的,原始值你只能覆盖,也不能干别的
例2:
    Grand.prototype.Lastname  = "Deng";
    function Grand (){

    }
    var grand = new Grand();
    Father.prototype = grand;
    function Father(){
        this.name = "xuming";
        this.fortune= {
            card : "vise",
        }
        this.num  = 100;                                  //在控制台son.num ++后,先出现的100什么都不是,然后再访问father.num = 100,son.num=101,所以son在将num取出来就行赋值后,就是自己的东西了,所以自己就多了一个num属性并且是101
    }
    var father = new Father();
    Son.prototype = father;
    function Son(){
        this.hobbit = "smoke";
    }
    var son = new Son();
3.谁调用的方法内部this就是谁-原型案例
例1:
    Person.prototype ={
        name : 'a',
        sayName : function(){
            console.log(this.name);              //sayName里面的this指向是,谁调用的这个方法,this就是指向谁,所以调用person.sayName()时结果为b,(person就是Person,一个是对象,一个是构造函数)
        }                                                       //所以当调用Person.prototype.sayName时,结果为a
    }
    function Person(){
        this.name = "b";
    }
    var person = new Person();
例2:
    Person.prototype ={
        height : 100,
    }
    function Person(){
        this.eat = function (){           //使用person.eat方法时只是改变了height属性的值并不会返回什么值,除非自己设定,但是在这里也没什么用,默认返回undefined
            this.height ++;               //在进行调用person.eat()时返回的是undefined,控制台每次访问返回的都是return值,因为这个eat方法默认是undefined,所以在自己没有设置return时,都返回undefined
        }                                           //在调用了person.eat()之后,person.height的值改变+1,但是person.__proto__(Person.prototype)原型的值不改变还是100。
    }
    var person = new Person();
补充:
    1.   var obj = {};                                   //这是对象自变量的创建形式,这个对象有原型,平时能用对象自变量就用对象自变量,最好不要用下面的那种形式。在公司中,数组和对象必须用自变量的写法,最好不要用其它方式
          var obj1 = new Object();              //Object() 这是系统给咱们提供的构建函数,上面语句和这个语句得实际上是一样的,在上一条语句上,系统会在内部实现var obj= new Object(),这个对象原型是obj1.__proto__ -- > Object.prototype
    2.
        Person.prototype = {} /*-- >Object.prototype*/      //person的原型就是对象自变量,最终就是Object.prototype
        function person(){

        }
4.Object.create(原型);的用法
例1:
    Person.prototype.name = "sunny";
    function Person(){

    }
    var person = Object.create(Person.prototype);              //Object.create(原型),这条语句就创建了一个以Person.prototype为原型的对象,但是你要是在自己的构造函数(工厂)中添加一些东西的话,那就不一样了,仅仅是原型一样了
5.绝大多数对象的最终都会继承自Object.prototype,但不是所有,因为下面的例题就是特例
例1:
    var obj = Object.create(null);                                         //Object.create(),括号里的东西只能是对象或者null,放置null的话,会生成一个空对象,什么也没有,原型也没有,访问obj时,是空的。但是你要是通过obj.__proto__  = {name : "sunny"};加上原型的话,系统让你加,访问obj时会有原型,但是系统不认,访问里面的属性时会显示undefined。
    总结:人为加的原型不好使,系统不会读里面的属性。所以说原型这个东西是隐式的内部属性,自己加是不管用的,就是系统给了,咱们可以去改,但是系统没有这个东西,自己加,系统是不认的。
例2:    var obj = Object.create(124);                                 //不能放原始值,会报错,但是可以放数组,数组也算object
6.toString()
    var num = 123;
    num.toString();                                                               //是正确的,因为数字经过包装类Number(123)可以一层一层地往上找,最终的原型一定含有toString属性,所以最终是可以访问的
    null.toString()或者undefined.toString()                         //是报错的,因为它俩不能经过包装类,没有原型,也不是对象,所以没有toString属性,或者说只有它俩和自己构造出的没有原型的东西没有toString,剩下的都有
   123.toString()                                                                  //也是错的,因为系统会把它看成浮点数,因为小数点优先级最高,所以会报错
 补充:
(1) var obj = {};  obj.toString();                                     //对象上面调用的toString是Object.prototype中的toString,毋庸置疑。
(2) var num = 134;                   
    num.toString();                                                            // -->new Number(num).toString();
    Number.prototype.toString = function(){                  // new Number原型就是Number.prototype,
                                                                                        // 而Number.prototype上面就有一个toString方法

    }
    Number.prototype.__proto__ = Object.prototype    //Number.prototype也有原型,它的原型就是Object.prototype,这就是原型链
                                                                                      //所以Number.prototype上面有toString属性,我就不用Object.prototype上面的tiString属性了,所以num.toString()调用的是自己重写过的,不是Object.prototype上的
   这里补充一个重写的概念,重写就是:原型上是有这个方法的,然后我自身又写了一个和原型上的方法,同一个名字但不同功能的方法叫做重写。叫同一个名字的函数的不同重写方式。
   重写一般是应用于后端静态语言,像java,C++等都有一些方法重写,一个类里面有很多方法,方法名字都不一样,返回值类型不同,形参列表不同,所以这叫重写,通过你返回值,形参列表的不同,不同传参调用不同的方法,这个叫真正意义上的重写。


 

猜你喜欢

转载自blog.csdn.net/LFY836126/article/details/81293546