zoukankan      html  css  js  c++  java
  • JavaScript常用技巧总结(持续添加中...)

    在我学习过程中收集的一些常用技巧:

    typeof x !== undifined 判断x是否已定义;
    x === Object(x)  判断x是否为对象;
    Object.keys(x).length 获取对象x所有可枚举的元素的个数;
    Object.getOwnPropotyNames(x).length 获取对象x所有元素的个数;
    注意:var p1 = Object.create(p);对象p1只继承了p的属性,但未继承它的属性描述符,此时p1的继承属性的描述符为空;
    for in循环遍历对象的所有可枚举属性,x.hasOwnPropoty(item)判断是否是自有属性;
    Object.prototype.toString.call(x).slice(8,-1) 获取对象x的类型;
    str.substring(index1,index2)和str.slice(index1,index2)虽然效果一样,但最好优先使用slice方法,str.substr(index,n)也是取一段字符串但第二个参数表示取的字符个数;
    !! a 或 Boolean(a) 获得一个变量a对应的布尔值;
    在构造函数内实行严格模式(首行加'use strict')可避免忘记用new命令来调用构造函数而引起的未知错误,或者在构造函数内添加判断this instanceof Foo看是否能生成实例,不能则返回一个实例;
    如果一个对象被freeze冻结了,那么他将不能添加、更改、删除所有属性的值,但仍然可通过在他的原型上添加属性来给他添加属性;若他的属性也是对象,则该属性指向该对象的引用不可更改,但对象本身是可以改变的;
    Array.apply(null,array1)调用Array构造函数来讲数组array1中的空元素变成undefined,数组的forEach方法会跳过空元素,但是不会跳过undefined,把undefined当着值对待;
    array1.forEach(callback(currentValue,index,array1),thisArg);其中可选参数thisArg指定在forEach内的this的指向;
    call、apply、bind这三个方法,来切换/固定this的指向,也可用来调用对象的原生方法,如Math.max.apply(null,array1)获得数组array1的最大值;
    call、apply绑定对象并指向方法,而bind仅绑定对象并返回新方法:var func2 = func1.bind(obj,x1,y1..)将方法func1绑定给obj对象,返回一个新方法并可指定预设参数值;
    因为每调用bind一次就会返回一个新函数,所以应该把这个新函数赋值给一个变量后再拿来用,防止无法取消绑定!
    理解this其实很简单
    this的指向是动态的,它指向:this所在函数的当前运行环境对象;若要多层使用this,则最好将this赋值给一个变量来在内层中使用var that = this;
    var a = {
    b: {
    m: function() {
    console.log(this.p);
    },
    p: 'Hello'
    }
    };
    a.b.m(); //Hello
    var hello1 = a.b.m; //此时hello实际上指代m函数本身,与a.b无关
    hello1();//undefined 当前运行环境内无属性p;
    var hello2 = a.b;
    hello2.m(); //Hello 当前运行环境为对象b
    工具函数:
    一、继承与多重继承的实现
    //父类1
    function SuperClass1(){
    this.x = arguments[0]||0;
    this.y = arguments[1]||0;
    }
    SuperClass1.prototype.add = function(x,y){return x+y;};
    SuperClass1.num1 = 0;
    //父类2
    function SuperClass2(){
    this.a = 1;
    }
    SuperClass2.prototype.sum1 = function(x,y){return x+y;};
    SuperClass2.prototype.sum2 = function(x,y){return x+y;};
    //子类(继承自父类1,同时继承了父类2的所有实例属性/对象属性)
    function Sub(){
    SuperClass1.apply(this,arguments);
    SuperClass2.call(this);
    this.z = 0;
    }
    Sub.prototype = Object.create(SuperClass1.prototype);//此处若省略Object.create()则子类和父类共享一个原型
    mixin(Sub.prototype,SuperClass2.prototype);
    Sub.prototype.divide = function(x,y){return x-y;};

    function mixin(toProto,fromProto){
    for(var item in fromProto){
    if(item !== 'constructor'){
    toProto[item] = fromProto[item];
    }
    }
    }
    var s1 = new Sub();
    console.log(s1) //Sub { x: 0, y: 0, a: 1, z: 0 }
    console.log(Object.getOwnPropertyNames(s1.constructor.prototype));
    //[ 'sum1', 'sum2', 'constructor', 'divide' ]
    二、完整的复制对象p(含所有自有属性和继承属性)
    function copyObject(p){
    //获取p的继承属性
    var o = Object.create(Object.getPrototypeOf(p));
    //获取p的自有属性(若使用for..in遍历p,则仅获得p的可枚举属性)
    Object.getOwnPropertyNames(p).forEach(function(item){
    var des = Object.getOwnPropertyDescriptor(p,item);
    Object.defineProperty(o,item,des);
    });
    return o;
    }
    复制任意对象(含任意可枚举属性)和Object.assign(o,p1,p2,..)一样,但assign方法兼容性差
    var extend = function (o, p) {
    for(var item in p){
    var des = Object.getOwnPropertyDescriptor(p,item);
    if(des&&(!des.writable
    ||!des.configurable
    ||!des.enumerable
    ||des.get
    ||des.set)){
    Object.defineProperty(o,item,des);
    }else{
    o[item] = p[item];
    }
    }
    };
  • 相关阅读:
    第一次冲刺02
    第一次冲刺01
    Android源码分析(十四)PackageManagerService服务分析
    Android源码分析(十三)ActivityManagerService服务分析
    Android源码分析(十二)ServiceManager服务分析
    Serializable和Parcelable之序列化
    ViewPager 相关使用
    AIDL介绍以及简单使用
    Android 四大组件 (五) 第五大组件
    Android 源码分析(十一) 事件传递机制
  • 原文地址:https://www.cnblogs.com/susufufu/p/5705813.html
Copyright © 2011-2022 走看看