• js--进阶知识点


    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/>
        <meta name="format-detection" content="telphone=no, email=no"/>
        <meta name="apple-touch-fullscreen" content="yes"/>
        <meta name="apple-mobile-web-app-capable" content="yes"/>
        <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
        <title>js严格模式</title>
    </head>
    <body>
    <a href="javascript:void (0);" class="clicka">点我</a>
    <a href="javascript:void (0);" class="clicka-btn">点我22</a>
    </body>
    <script type="text/javascript">
        'use strict';
        var arr=[1,3,4,5,9,12,6];
        function fun1(argument) {
            console.log("严格模式");
            // body...
        }
        fun1();
    
       /* function fun2(){
            var arguments = [];
            console.log("arguments 严格模式下不能再定义");
        }
        function arguments (){
            console.log("arguments 严格模式下不能再定义,非严格模式可以");
        }*/
    
    //隐式转换
    //字符串+其他  得到的仍是字符串
    console.log('8' | '1'); 
    
    //使用原始类型替代对象包裹(谨记:对象包装的原始类型和原始类型在比较相等的时候,它们具有不同的表现行为。)
    var s = new String('hello');
    var s2= new String('hello');
    var str=s+'world';
    console.log(typeof 'hello'); // string
    console.log(typeof s); // object
    console.log(s===s2); //false
    console.log(s==s2); //false
    //str.someProperty = 'some';
    //console.log(str.someProperty); // 输出undefined,但是如果 obeject.属性,则正确输出值
    
    //==  在比较两边的值时,会隐性的把它们转换成同一类型的值,然后才会进行比较
    //=== 直接比较,不涉及隐性类型转换。
      
    //尽量少用全局变量,尽量使用局部变量
    //若不加var则是隐性的定义了全局变量,所以定义变量时一定要加var
    
    // 闭包:熟练掌握闭包
    function Container(){
        var arr=[];
        return {
            getItem:function(index){
                return arr[index];
            },
            addItem:function(obj){
                var index=arr.push(obj);
                return index-1; //返回添加元素的第一个元素
            },
            length:function(){
                return arr.length;
            }
        }
    }
    var c = Container();
    console.log("con的长度"+c.length()); // 0
    var index1 = c.addItem({name: 'dreamapple'});
    console.log(index1); // 0
    console.log(c.length()); // 1
    console.log(c.getItem(index1)); // Object {name: "dreamapple"}
    
    //变量声明提升(代码块中的变量声明会被隐式地提升到封闭函数的顶部)
    console.log(test_bl);
    // ***相当于把 var test提升到顶部 赋值部分 test = 1 还是在原来的位置;
    var test_bl=9; //若此行注释,则会报错,若不注释,则输出 undefined
    
    //2.6 使用立即调用的函数表达式创建局部作用域
    // 新的函数才会产生新的作用域,JavaScript的循环没有新的作用域产生。
    var testArr=[4,5,6];
    function generateFun(arr){
        var result = [];
        var len=arr.length;
        for (var i=0; i <len; i++) {
            
           (
            function(j){
                result[j]=function(){
                    return arr[j];
                }
            }
            )(i);
        }
        return result; //返回,外面才会访问到result
    }
    // @2 产生新的函数
    var g2 = generateFun(testArr);
    console.log(g2[0]()); //4
    console.log(g2[1]()); //5
    console.log(g2[2]()); //6
    
    //2.6-2 闭包方式2
    function genetateFun2(arr){
        var result=[];
        var len=arr.length;
        for (var i = 0; i < len.length; i++) {
            (
                function(i){
                  var j=i; //注意此处
                  result[i]=function(){
                    return arr[j];
                  }
                }
    
                )()
        }
        return result;
    }
    var g3 = generateFun(testArr);
    console.log(g3[0]()); //4
    console.log(g3[1]()); //5
    console.log(g3[2]()); //6
    //2.7 命名的表达式函数
    function fun_right_mm(){
        console.log('fun_right_mm');
    }
    var fun_mm = function fun_mm_name(){
       console.log('fun本身');
       return  fun_right_mm();
    }
    console.log(fun_mm()); //undefined
    //console.log(fun_mm_name());// fun_mm_name is not defined
    //尽量用所以尽量使用匿名的函数表达式
    //2.8 局部函数调用
    
    //3.1理解函数调用,方法调用及构造函数调用之间的不同
    /*方法调用将被查找方法属性的对象作为调用接受者。
    构造函数需要通过new运算符调用,并产生一个新的对象作为其接受者。*/
    function heelo(){
        console.log('hello函数调用');
    }
    heelo();
    var heeloObj={
        welcome:function(){
            console.log('方法调用'+this.name);
        },
        name:"小红"
    }
    heeloObj.welcome();
    function HeeloContruct(name,age){
        this.name=name;
        this.age=age;
        console.log('构造函数的名字是'+this.name+', and my age is ' + this.age);
    }
    var heeloCon=new HeeloContruct('小明',26);
    //3.2熟练掌握高阶函数(高阶函数是那些将函数作为参数或返回值的函数。)[1,3,4,5,9,12,6]
    var arr_gj=arr.sort(function(x,y){
        if(x>y){
            return 1;
        }else{
            return -1;
        }
    })
    console.log(arr_gj);//排序
    var arr_gj2=arr.map(function(x) {
        return x*2+1;
    });
    console.log(arr_gj2);
    var arr_gj_aIndex='a'.charCodeAt(0);//于指定位置的字符的编码
    //使用高阶函数
    function creatStr(n,cb){
        var str='';
        for (var i = 0; i < n; i++) {
            str+=cb(i);
        }
        return str;
    }
    //创建一个随机字符串
    var str_sj_str=creatStr(10,function(){
        return String.fromCharCode(Math.floor(Math.random()*26)+arr_gj_aIndex);
        /*fromCharCode() 可接受一个指定的 Unicode 值,然后返回一个字符串*/
    })
      console.log(str_sj_str);
      //创建一个随机数
      var str_sj_num=creatStr(10,function(){
        return Math.floor(Math.random()*26);
      })
      console.log(str_sj_num);
      //3.3 使用call方法自定义接受者来调用方法
      var objCall={
        callWay:function(msg){
            console.log('callWay:'+this.name+'函数参数:'+msg);
    
        },
        name:"objCall-1-name"
      }
      var objCall2={
        name:"objCall2-name"
      }
      objCall.callWay.call(objCall2,'haha');// 第一个参数是方法的调用者,剩余的参数就是原函数的参数
    
      // 高阶函数使用call
    function compute(arg) {
        var sum = 0;
        for(var i = 0; i < arg.length; i++) {
            sum += arg[i];
        }
        return sum;
    }
    
    function highFunc() {
       //console.log(arguments.length); //5
        return compute.call(null, arguments);
    }
    
    console.log(highFunc(1, 2, 3, 4, 5)); // 15
    /*
    使用call方法自定义接受者来调用函数。
    使用call方法可以调用在给定的对象中不存在的方法。
    使用call方法定义高阶函数允许使用者给回掉函数指定接收者。*/
    //3.3  使用apply方法通过不同数量的参数调用函数
    /*使用apply方法指定一个可计算的参数数组来调用可变参数的函数。
    使用apply方法的第一个参数给可变参数的方法提供一个接收者。*/
    function compute2() {   //**使用arguments创建可变参数的函数
        var sum = 0;
        for(var i = 0; i < arguments.length; i++) {
            sum += arguments[i];
        }
        return sum;
    }
    function wrapper(arr) {
        return compute2.apply(null, arr); // 给compute函数传递多个参数
    }
    var apply_arr=[1, 2, 3, 4, 5];
    console.log(wrapper(apply_arr));
    /*call与apply的区别
        apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。
    
        call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。 
    
        实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。
    
    */
    //3.8 3.9 待研究
    
    //3.11  不要信赖函数的对象的toString方法。因为不同的引擎下调用toString方法的结果可能不同
    var str_tostring=45955444;
    console.log(typeof(str_tostring)); //number
    console.log(typeof(str_tostring.toString())); //string
    var str_tostring_hs=function(x) {
        return x + 1;
    }
    console.log(str_tostring_hs.toString());/*输出:function (x) {
        return x + 1;
    }*/
    console.log(typeof (str_tostring_hs)); //function
    console.log(typeof (str_tostring_hs.toString()));//string
    
    //4.1 prototype,getPrototypeOf和__proto__之间的不同
    /*C.prototype属性是new C()`创建的对象的原型。
    Object.getPrototypeOf(obj)是ES5中检索对象原型的标准函数。
    obj.__proto__是检索对象原型的非标准方法。
    类是由一个构造函数和一个关联的原型组成的一种设计模式。
    
    */
    function protoStudent(name,age){
        this.name=name;
        this.age=age;
    }
    protoStudent.prototype.sayHello=function(){
        console.log('hello prototype student'+this.name);
    }
    var s = new protoStudent('dreamapple', 22); //声明函数
    s.sayHello(); //调用方法
    
    console.log(protoStudent.prototype === s.__proto__); // true
    console.log(protoStudent.prototype === Object.getPrototypeOf(s)); // true 要常用getPrototypeOf()
    
    //4.7 只将实例状态存储在实例对象中
    /*
    共享可变数据可能会出现问题,因为原型是被所有的实例共享的。
    将可变的实例状态存储在实例对象中。*/
    function TreePro(value){
        this.value=value;
        //this.children=[];
    }
    TreePro.prototype={
        children:[],
        addChild:function(value){
            this.children.push(value);
        }
    };
    var left=new TreePro(1);
    left.addChild(2);
    left.addChild(3);
    console.log(left.children);//[2, 3]
    var right= new TreePro(2);
    right.addChild(4);
    right.addChild(5);
    console.log(right.children);//[2, 3, 4, 5]
    var top22= new TreePro(7);
    top22.addChild(left);
    top22.addChild(right);
    console.log(left.children);//[2, 3, 4, 5, {value:1}, {value:2}]
    console.log(top22.children);//同上
    // 可以发现,left right top22改变,则属性都跟着变化,所以,原型为所有实例共享,应该将可变的实例状态存储在实例对象中
    function TreePro1(value){
        this.value=value;
        this.children=[];
    }
    TreePro1.prototype={
        addChild:function(value){
            this.children.push(value);
        }
    };
    var left1 = new TreePro1(1);
    left1.addChild(2);
    left1.addChild(3);
    console.log(left1.children); // [ 2, 3 ]
    var right1 = new TreePro1(4);
    right1.addChild(5);
    right1.addChild(6);
    var top1 = new TreePro1(7);
    top1.addChild(left1);
    top1.addChild(right1);
    console.log(left1.children); // [ 2, 3 ]
    console.log(top1.children); // [ { value: 1, children: [ 2, 3 ] },{ value: 4, children: [ 5, 6 ] } ]
    
    //4.9 在子类的构造函数中调用父类的构造函数
    
    //定义一个父类
    function parentPro(name,age){
        this.name=name;
        this.age=age;
    }
    parentPro.prototype.sayHello=function(){
        console.log('my name is'+this.name);
    }
    //定义我们的子类
    function ChildPro(name,age,school){
        parentPro.call(this,name,age);
        this.school=school;
    }
    //**将子类与父类的原型关联
    // Object.create() 一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的
    ChildPro.prototype=Object.create(parentPro.prototype);//使用Object.create()函数来构造子类的原型对象以避免调用父类的构造函数。
    ChildPro.prototype.getSchool = function(){
        console.log('my school is'+ this.school);
    } 
    var Childppro=new ChildPro('namehong',12,'guangming')
    Childppro.getSchool();//my school isguangming
    Childppro.sayHello();//my name isnamehong
    //4.12 将原形视为实现的细节 对象是接口,原型是实现。
    //提供参数默认值应当采用测试undefined的方式,
    // 6.5 使用结构类型(也称为鸭子类型)来设计灵活的对象接口。
    // 我们可以使用结构类型
    function rectangle1_jiegou(width, length) {
        var _width = width,
            _length = length;
        return {
            getArea: function() {
                return _width * _length;
            }
        }
    }
    var r2 = rectangle1_jiegou(100, 200);
    console.log(r2.getArea()); // 20000
    // 6.6 使用ES5提供的Array.isArray方法测试真数组。
    // 6.7避免过度的强制转换
    function square(x) {
        // 这里会进行强制的类型转换
        return x * x;
    }
    console.log(square('3')); //
    // 一种比较好的方式,我们在函数内部判断参数是否是一个数字
    function square1(x){
        if (typeof (x)==='number') {
           return x*x;
        }
      throw new Error('请传递正确的参数类型!');
    }
    console.log(square1(3));
    // 6.3 ***使用extend函数抽象出从选项对象中提取值的逻辑。
    //定义一个接受参数的选项对象的函数
    function AlertSelect(obj){
        this.level=obj.level;
        this.msg=obj.msg;
    }
    var ale = new AlertSelect({
        level:0,
        msg:"hello alertselect"
    });
    console.log(ale);//AlertSelect {level: 0, msg: "hello alertselect"}
    // 当然如果一些参数是必选的话,我们把他们单独拿出来,而且参数的选项对象上的属性不是必选的
    function AlertSelect1(level,msg,options){
        this.level=level;
        this.msg=msg;
        for (var p in options) {
            this[p]=options[p];//遍历属性并赋值给this
        }
    
    }
    var ale1=new AlertSelect1(1,'find error',{
        count:9,
        theme:'default'
    })
    console.log(ale1);//AlertSelect1 {level: 1, msg: "find error", count: 9, theme: "default"}
    //6.3的重点来啦
    // 使用extend函数扩展我们的参数对象
    function extend(target, source) {
        if(source) {
            for(var p in source) {
                var val = source[p];
                if('undefined' !== typeof val) {
                    target[p] = val;
                }
            }
        }
        return target;
    }
    // 升级原来的构造函数
    function Alert2(level, msg, options) {
        var opt = extend({
            level: level,
            msg: msg
        });
        opt = extend(opt, options);
        extend(this, opt);
    }
    var ale2 = new Alert2(2, 'bug', {
        count: 1,
        theme: 'highlight'
    });
    console.log(ale2);//Alert2 {level: 2, msg: "bug", count: 1, theme: "highlight"}
    
    //5.1 使用Object的直接实例构造轻量级的字典
    // 使用一个对象作为字典来使用
    var dict1 = {
        key1: 'value1',
        key2: 'value2',
        key3: 'value3'
    };
    // 使用Object.getPrototypeOf() 避免使用 __proto__
    var dict1P = Object.getPrototypeOf(dict1);
    dict1P.say2 = function(){};
    var props3 = [];
    for(var p in dict1) {
        props3.push(p);
    }
    console.log(props3); // [ 'key1', 'key2', 'key3', 'say' ]
    
    // 按照顺序的输出要使用数组,不能使用对象
    var info1 = [
        {name: 'dream'},
        {'1': '10'},
        {'A': function() {}}
    ];
    
    for(var i = 0; i < info1.length; i++) {
        for(var kk in info1[i]) {
            if(Object.hasOwnProperty.call(info1[i], kk)) {
                console.log(kk + ' : ' + info1[i][kk]);
            }
        }
    }
    //并其第5部分
    //5.9  在类数组对象上复用通用的数组方法
    function fn() {
        console.log(arguments);
        console.log([].slice.call(arguments, 0)); //[1, 2, 3]
        console.log(['array'].concat([].slice.call(arguments)));//[ 'array', 1, 2, 3 ]
    }
    fn(1, 2, 3);
    </script>
    </html>
  • 相关阅读:
    L2-004. 这是二叉搜索树吗?
    CF934A A Compatible Pair
    CF937B Vile Grasshoppers
    CF940B Our Tanya is Crying Out Loud
    ZOJ 3182 Nine Interlinks
    ZOJ 3175 Number of Containers
    Codeforces Round #193 (Div. 2) B
    CodeForces 149D Coloring Brackets
    POJ 2653 Pick-up sticks(计算几何)
    UVA 12506 Shortest Names
  • 原文地址:https://www.cnblogs.com/lanyueff/p/6794857.html
Copyright © 2020-2023  润新知