zoukankan      html  css  js  c++  java
  • Javascript 高级程序设计--总结【二】

     **********************  Chapter 6  **********************

     属性:

             数据属性:

                       Configurable: 能否通过delete 删除属性,默认true

                       Enumerable: 能否通过 for-in 循环返回属性,默认true

                       Writeble: 能否修改属性的值

                       Value:属性的数据值

                       使用 Object.defineProperty(obj,'prop',{}) 来定义属性,这种方式的默认值都是 false ,不建议 IE8 中使用

                       var person={};

                       Object.defineProperty(person,'name',{

                                writable:false,

                                value:"test"

                       });

                       如果设置了configurable:false, 那么就不能再设置更改其他属性,否则会抛出错误

            

             访问器属性:

                       gettersetter  configurable enumerable

                                var book={

                                         _year:2010,

                                         edition:1

                                };

                                Object.defineProperty(book,'year',{

                                         get:function(){

                                                   return this._year;

                                         },

                                         set:function(value){

                                                   if(value>2010){

                                                            this._year=value;

                                                            this.edition+=value-2010;

                                                   }

                                         }

                                });

                                book.year=2011;

                                console.log(book.edition);

                                //另外一种方式

                                book.__defineGetter__('year',function(){

                                         return this._year;

                                });

                                book.__defineSetter__('year',function(value){

                                         if(value>2010){

                                                            this._year=value;

                                                            this.edition+=value-2010;

                                                   }

                                });

                       defineProperties() 定义多个属性

                                Object.defineProperties(book,{

                                         _year:{

                                                   value:2010

                                         },

                                         edition:{

                                                   value:1

                                         }

                                })

             读取属性的特性 getOwnPropertyDescriptor() :IE9+       

                       var desc = Object.getOwnPropertyDescriptor(book,'_year')        

                       console.log(desc.configurable);

    创建对象:

             工厂模式:

                       function createPerson(name,age){

                                var obj = new Object();

                                obj.name=name;

                                obj.age=age;

                                obj.sayName = function(){

                                         console.log(this.name);

                                }

                                return obj;

                       }

                       var p1 = createPerson('test',15);

                       var p2 = createPerson('test2',18);          

                       这种模式的缺点就是:不能检测对象的所属类型

            

             构造函数模式:

                       function Person(name.age){

                                this.name=name;

                                this.age=age;

                                this.sayName=function(){

                                         console.log(this.name);

                                }

                       }

                       var p1 = new Person('jj',20);

                       var p2 = new Person('ee',22);

                       console.log(p1.constructor==Person);//true

                       console.log(p2.constructor==Person);//true

                       console.log(p1 instanceof Person);//true

                       构造函数本质也是函数,区别只是在于如何调用,构造函数使用 new 操作符地哦啊用,

                       如果看做普通函数调用,本质也没什么区别,this 关键字可指向window

                                //普通函数调用

                                Person('gl',22);

                                window.sayName();

                                var o = new Object();

                                Person.call(o,'cl',19);

                                o.sayName();

                       问题:每个对象里面的方法都会创建一个Function的新实例,但是如果方法体定义在全局中,那么将会声明太多的全局函数    

            

             原型模式:

                       function Person(){

                       }

                       Person.prototype.name='aa';

                       Person.prototype.age=18;

                       Person.prototype.sayName=function(){

                                console.log(this.name);

                       }

                       Person.prototype.isPrototypeOf(p1);//true

                       Object.getPrototypeOf(p1)==Person.prototype;//true

                       var p1 = new Person();

                       console.log(p1.name);

                       p1.sayName();

                      

                       p1.hasOwnProperty('name');//false

                       原型链的属性搜索:从实例本身开始找,如果没有就会去原型对象中寻找

                       同样,实例对象里面的同名属性会覆盖掉原型对象中的同名属性  delete

                       ES5中,Object.getOwnPropertyDescriptor() 只能获取实例对象中属性,要获取原型对象必须在原型对象上调用此方法

                       in操作符:

                                只要是能访问到,不管实例还是原型上都为true, 如果

                                'name' in p1;//true

                                Object.keys(p1);// for-in

                                Object.keys(Person.prototype);//["name", "age", "sayName"]0: "name"1: "age"2: "sayName"length: 3__proto__: Array[0]

                                Object.getOwnPropertyNames(Person.prototype);//["constructor", "name", "age", "sayName"]

                       字面量的原型对象声明        

                                    function Person() {

                                         }

                                         //这里使用了字面量的方式创建原型对象,但是这个原型的constructor 就不是指向Person,而是Object

                                         Person.prototype = {

                                                   //constructor: Person,//constructor 的enumerable 会设置为true,可迭代出去

                                                   name: "test",

                                                   age: 18,

                                                   sayName: function () {

                                                            console.log(this.name);

                                                   }

                                         }

                                         var p = new Person();

                                         console.log(p.constructor);//Object

                                         //手动定义的方式  ES5 兼容

                                         Object.defineProperty(Person.prototype, 'constructor', {

                                                   enumerable: false,

                                                   value: Person

                                         });

                       原型的动态性:

                                声明变量之后,再更改原型对象,也是可以再对象中使用的

                                var p = new Person();

                                Person.prototype.run = function () {

                }

                p.run();

                               

                                //注意: 以下是重写了原型的方式

                                function Person() {

                                }

                                var p = new Person();

                                //重写了原型对象, p 对象还是指向原来的原型对象

                                Person.prototype = {

                                    constructor: Person,

                                    name: "test",

                                    sayName: function () {

                                        console.log(this.name);

                                    }

                                }

                                //原来的原型对象中没有此方法

                                p.sayName();//error: p.sayName is not a function

                               

                       扩展原生对象的原型:

                                String.prototype.startWith=function(){

                                         //......

                                }

                       原型对象的问题:

                                属性的引用类型问题:

                                function Person() {

                                }

                                //重写了原型对象, p 对象还是指向原来的原型对象

                                Person.prototype = {

                                         constructor: Person,

                                         name: "test",

                                         hobbies:['basketball','football'],

                                         sayName: function () {

                                                   console.log(this.name);

                                         }

                                }

                                var p = new Person();

                                p.hobbies.push('a');

                                console.log(p.hobbies);//["basketball", "football", "a"]

                               

                                var p1 = new Person();

                                console.log(p1.hobbies);//["basketball", "football", "a"]      

             组合使用构造函数模式和原型模式【推荐】:

                       function Person(name, age) {

                this.name = name;

                this.age = age;

                this.hobbies = [];

            }

            Person.prototype = {

                constructor: Person,

                sayName: function () {

                    console.log(this.name);

                }

            };

             动态原型模式:

                       function Person(name, age) {

                this.name = name;

                this.age = age;

                this.hobbies = [];

                //这样子相当于只会执行一次的定义

                if (typeof this.sayName != 'function') {

                    Person.prototype.sayName = function () {

                        console.log(this.name);

                    }

                }

            }

             寄生构造函数模式【基本不用】:

                       function Person(name,age) {

                var o = new Object();

                o.name = name;

                o.age = age;

                o.sayName = function () {

                    console.log(this.name);

                }

                return o;

            }

            var p = new Person('kk', 19);

                               

             稳妥构造函数模式【基本不用】:

                       不使用new 和 this 关键字

                       function Person(name,age) {

                var o = new Object();

                o.sayName = function () {

                    console.log(name);//这里的name 只有方法内部才能访问的到

                }

                return o;

            }

                               

    继承:

             原型链【很少单独使用】:

                       prototype属性实现继承,每一个实例对象都有一个prototype 的属性

                       所有的函数的默认原型都是Object的实例,默认的原型实例都包含一个指针指向 Object.prototype

                      

                                instanceof()isPrototypeof() 确定实例和原型的关系,只要出现在原型链中的对象就会返回true

                                Person.prototype.isPrototyprOf(obj);

                       原型链继承一定不要使用字面量的方式,因为这样会导致重写原型,之前的继承会失效

                       继承添加的方法一定要在继承了原型链之后    

                      

                       原型链问题:

                                引用对象共享实例问题

                                function Person(){

                                         this.colors=['red','blue'];

                                }

                                function Man(){

                                }

                                Man.prototype=new Person();

                                var m  =new Man();

                                m.colors.push('blink');

                                var m1 = new Man();

                                console.log(m.colors);//['red','blue','blink']

                                console.log(m1.colors);//['red','blue','blink'] 

             借用构造函数【很少单独使用】:

                                function Base(name){

                                         this.name=name;

                                }

                                function Sub(){

                                         Base.call(this,'test');

                                         this.age=age;

                                }

                                var s = new Sub();

                       问题:方法都只能在构造函数中定义,函数不能复用,并且父类的原型方法不可见

             组合继承:

                                function Base(name){

                                         this.name=name;

                                }

                                Base.prototype.sayName=function(){

                                         console.log(this.name);

                                }

                                function Sub(name,age){

                                         Base.call(this,name);

                                         this.age=age;

                                }

                                Sub.prototype=new Base();

                                Sub.prototype.sayAge=function(){

                                         console.log(this.age);

                                }

                                var s1 = new Sub('kk',18);

                                s1.sayName();

                                s1.sayAge();

             原型式继承:

                                function object(o){

                                         function F(){}

                                         F.prototype=o;

                                         return new F();

                                }

                                var p = {name:'qq',hobbies:['a','b']};

                                var p1 = object(p);

                                p1.hobbies.push('c');

                                console.log(p1.hobbies);//["a", "b", "c"]

                                var p2 = object(p);

                                console.log(p2.hobbies);//["a", "b", "c"]        

                       ES5 的 Object.create() 就是使用的这个方法

                                //类似 defineProperties 的参数使用方式

                                var p3 = Object.create(p,{

                                         name:{

                                                   value:'newP'

                                         }

                                });

                                console.log(p3.name);//newP

             寄生式继承:

                                function createObj(obj){

                                         var clone = object(obj);

                                         clone.run=function(){

                                                   console.log('running');

                                         }

                                         return clone;

                                }

                                var p4 =  createObj(p);

                                p4.run();

             寄生组合式继承【最理想的继承范式】:

                       function object(o){

                                function F(){}

                                F.prototype=o;

                                return new F();

                       }

                       function inherit(sub,base){

                                var proto = object(base.prototype);

                                proto.constructor = sub;

                                sub.prototype=proto;

                       }

                       function Base(name){

                                this.name=name;

                                this.colors=['red'];

                       }

                       Base.prototype.sayName=function(){

                                console.log(this.name);

                       }

                       function Sub(name,age){

                                Base.call(this,name);

                                this.age=age;

                       }

                       inherit(Sub,Base)

                       Sub.prototype.sayAge=function(){

                                console.log(this.age);

                       }

                       var sub = new Sub('kk',18);

                       sub.sayName();

                       sub.sayAge();

                       console.log(sub.__proto__.constructor);// Sub()

                               

    ************************  Chapter 7 函数表达式       ************************                  

    func.name;//输出函数名称

                 //递归方式  arguments.callee() 或 以下方式

            var factorial = (function f(num) {

                if (num <= 1) {

                    return 1;

                } else {

                    return num * f(num - 1);

                }

            });

    闭包:

             作用域链本质上是一个指向变量对象的指针列表

             闭包会携带包含它函数的作用域链,更加占用内存资源

                 function createF() {

                var arr = new Array();

                for (var i = 0; i < 10; i++) {

                    //1. 这种方式的闭包,都会引用到外部函数的 活动对象 i, 最终的值都一样

                    //arr[i] = function () {

                    //    console.log(i);

                    //}

                    //2. 这种优化的方式,就可以实现每次返回不同的值

                    arr[i] = function (num) {

                        return function () {

                            console.log(num);

                        }

                    }(i);//这里立即执行了函数,所以传入参数会让num更改

                }

                return arr;

            }

            var res = createF();

            for (var i = 0; i < res.length; i++) {

                res[i]();

            }

             内存泄漏问题:

                       function assignHandler() {

                var ele = document.getElementById("ele")

                ele.onclick = function () {

                    console.log(ele.id);//这里相当于一直引用着ele 元素,导致循环引用,无法释放

                }

            }

            function assignHandler() {

                var ele = document.getElementById("ele")

                var id = ele.id;

                ele.onclick = function () {

                    console.log(id);//正确用法

                }

                ele = null;//释放引用

            }

    模仿块级作用域:                           

                       function test() {

                for (var i = 0; i < 10; i++) {

                    //alert(i);

                }

                console.log(i);//10

                var i;//声明会被忽视,但是赋值才会覆盖  i=100

                console.log(i);//10

            }

            test();

             模仿块级作用域:

                       var f = function () {

                console.log('f');

            }

            f();

            //块级作用域

            (function () { console.log('f'); })();

                      

                       //里面的都是块级作用域

                       (function () {

                var btn = document.getElementById("btn");

                btn.onclick = function () {

                    console.log('onclick');

                }

                console.log('f');

            })();  

    私有变量:

                       function Person() {

                                //特权方法,访问私有变量          

                                this.getName = function () {             

                                         return name;           

                                };               

                                //特权方法,访问私有变量          

                                this.setName = function (val) {                 

                                         name = val;               

                                };               

                       }                

             静态私有变量:

                       function () {

                var privateVal = 10;

                function privateF() {

                    return false;

                };

                //这里没有使用var ,所以是全局的

                Person = function (val) {

                    name = val;

                };

                Person.prototype.getName = function () {

                    return name;

                }

                Person.prototype.setName = function (val) {

                    name = val;

                }

            })();

            var p1 = new Person('t1');//t1

            console.log(p1.getName());

            var p2 = new Person('t2');

            console.log(p1.getName());//t2 由于是静态的,所以都改变了

            console.log(p2.getName());//t2

                               

             模块模式(单例):

                       var singleton = function () {

                var privateVal = 10;

                function privateFun() {

                    return false;

                }

                return {

                    pubProp: true,

                    pubMethod: function () {

                        privateVal++;

                        return privateFun();

                    }

                };

            }();

            var application = function () {

                var components = new Array();

                components.push(new BaseComponent());

                return {

                    getCompCount: function () {

                        return components.length;

                    },

                    registerComp: function (component) {

                        if (typeof component == 'object') {

                            components.push(component);

                        }

                    }

                };

            }();

            

             增强的模块模式:

                       var singleton = function () {

                var privateVal = 10;

                function privateFun() {

                    return false;

                }

                //所谓的增强就是指定了返回类型

                var object = new CustomType();

                object.pubProp = true;

                object.pubMethod = function () {

                    privateVal++;

                    return privateFun();

                };

                return object;

            }();

                       var application = function () {

                var components = new Array();

                components.push(new BaseComponent());

                //所谓的增强就是指定了返回类型

                var app = new BaseComponent();

                app.getCompCount = function () {

                    return components.length;

                };

                app.registerComp = function (component) {

                    if (typeof component == 'object') {

                        components.push(component);

                    }

                };

                return app;

            }();   

                      

                               

                               

                               

    严格模式:

             eval赋值会导致错误;//eval='a'

             gettersetter, 没有设置就访问会报错

    ************************  Chapter 9 客户端检测       ************************                  

    能力检测:

             浏览器能力检测

                                if(obj.property){

                                         //使用obj.property 方法

                                }

                      

                       尽量使用 typeof 进行检测

                                function hasSort(){

                                         return typeof  obj.sort == 'function';

                                }

                       //IE

                       typof document.createElement == 'function'

                       IE9 之后所有的DOM方法才会返回 'function',因为IE8 之前的所有宿主对象都是COM对象,返回的是'object'

                       var xhr = new ActiveXObject("Microsoft.XMLHttp");

            if (xhr.open) {//函数作为属性检测 IE会发生错误,使用typeof 会放回 'unknow'

            }

            function isHostMethod(object, prop) {

                var t = typeof object[prop];

                // IE typeof xhr.open 这里会返回'unknow'

                return t == 'function' || (!!(t == 'object' && object[prop])) || t == 'unknow';

            }

            var res = isHostMethod(xhr, 'open');//true

             navigator.vendor;//浏览器的品牌

    怪癖检测(略):

             var obj = {

                       toString: function () {

                                console.log('string');

                       }

             };

             for (var i in obj) {

                       alert(i);

             }

            

    用户代理检测:

             IE7 和 IE8 的兼容模式:

                       IE7  navigator.userAgent 返回的是 MSIE 7.0, 没有trident 标记

                       IE8 的兼容模式 navigator.userAgent 返回的是 MSIE 7.0, 有trident 标记

             IE8:

                       navigator.userAgent 返回的是 MSIE 8.0

            

             Gecko:

                       //默认加密方式U,不会显示

                       "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0"

            

             用户代理字符串检测技术:

                       五大呈现引擎:IEGeckoWebKitKHTMLOpera

                      

                       ?: 表示不捕获分组

  • 相关阅读:
    关于浏览器的内核 版本 发展 详解
    js判断浏览器内核 及ie的版本问题
    插入flash代码
    大前端学习笔记【七】关于CSS再次整理
    其实,程序员没有我想象得那么简单(算是2016的简单总结吧...)
    大前端学习笔记整理【七】HTTP协议以及http与https的区别
    大前端学习笔记整理【六】this关键字详解
    大前端学习笔记整理【五】关于JavaScript中的关键字——this
    大前端学习笔记整理【五】rem与px换算的计算方式
    大前端学习笔记整理【四】LESS基础
  • 原文地址:https://www.cnblogs.com/yougmi/p/8980035.html
Copyright © 2011-2022 走看看