**********************  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, 那么就不能再设置更改其他属性,否则会抛出错误

访问器属性:

getter\setter  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'

getter\setter, 没有设置就访问会报错

************************  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"

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

五大呈现引擎:IE\Gecko\WebKit\KHTML\Opera

?: 表示不捕获分组

Javascript 高级程序设计--总结【二】的更多相关文章

  1. javascript 高级程序设计 十二

    1.组合使用原型模式和构造函数模式: 由于原型模式创建对象也有它的局限性------有智慧的人就把原型模式和构造函数模式进行了组合. function Person(name, age, job){/ ...

  2. JavaScript高级程序设计学习(二)之基本概念

    任何语言的核心都必然会描述这门语言基本的工作原理.而描述的内容通常都要涉及这门语 言的语法.操作符.数据类型.内置功能等用于构建复杂解决方案的基本概念.如前所述, ECMA-262通过叫做 ECMAS ...

  3. 读书时间《JavaScript高级程序设计》二:面向对象

    接着上次的进度,开始看第6章. 第6章 面向对象的程序设计 理解对象 创建自定义对象最简单的方式就是创建一个 Object 的实例,然后为它添加属性和方法. var person = new Obje ...

  4. javascript 高级程序设计(二)-在html中使用javascript

    <script> async 可选 charset 可选 defer 可选 language 已废弃 src 可选 type 可选

  5. JavaScript高级程序设计(二)

    一.函数 1.1 JS中函数无重载,同一作用域下定义两个函数,而不会引发错误,但真正调用的是后面定义的函数.例如: function doAdd(iNum){ alert(iNum+100); } f ...

  6. 《Javascript高级程序设计》阅读记录(二):第四章

    这个系列之前文字地址:http://www.cnblogs.com/qixinbo/p/6984374.html 这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较 ...

  7. 《JavaScript高级程序设计(第3版)》笔记-序

    很少看书,不喜欢看书,主要是上学时总坐不住,没有多大定性,一本书可以两天看完,随便翻翻,也可以丢在角落里几个月不去动一下. 上次碰到了<JavaScript高级程序设计(第3版)>感觉真的 ...

  8. 读javascript高级程序设计08-引用类型之Global、Math、String

    一.Global 所有在全局作用域定义的属性和方法,都属于Global对象. 1.URI编码: encodeURI():主要用于对整个URI编码.它不会对本身属于URI的特殊字符进行编码. encod ...

  9. JavaScript高级程序设计学习(三)之变量、作用域和内存问题

    这次讲的主要是变量,作用域和内存问题. 任何一门编程语言,都涉及这三个. 变量,比如全局变量,局部变量等,作用域,也分全局作用域和方法作用域,内存问题,在java中就涉及到一个垃圾回收的问题,由于ja ...

  10. javascript 高级程序设计 一

    前言: 作为一个即将毕业.正在实习的大学生,我也默默的进入了开发者的行列.从一开始的c#编码狗到java程序员再到现在的JS开发者,我一直 希望自己可以在这个'万恶'的互联网时代走的更远.但是我还是一 ...

随机推荐

  1. C语言最最最基础部分(a+b为例)

      此篇为C语言最基础的部分知识简单概括,对C语言有一定了解的同学建议绕道哦~另外,文底附有此文知识点详细了解的链接. 下面我们以“a+b”为例,分析这个程序的组成. #include<stdi ...

  2. 手把手教你学会用Spring AOP

    用了Spring很长时间了,一直想写些AOP的东西,但一直没有空闲,直到现在项目稍微进入正轨了,才赶紧写写.废话不多说,先从AOP入门开始,后面再介绍AOP的原理(JDK动态代码和CGLIB动态代码的 ...

  3. java学习-消息队列rabbitmq的组成

    rabbitMQ组成部分 rabbitmq有以下组成部分,分别为: 1. Server(broker)接受客户端连接,实现AMQP消息队列和路由功能的进程 2.虚拟主机virtual host虚拟主机 ...

  4. epoll的ET和LT模式

    epoll有两种模式,Edge Triggered(简称ET) 和 Level Triggered(简称LT). 在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会通知,而采用 ...

  5. Java并发编程笔记之CyclicBarrier源码分析

    JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复 ...

  6. Docker实践:python应用容器化

    一.前言 容器使用沙箱机制,互相隔离,优势在于让各个部署在容器的里的应用互不影响,独立运行,提供更高的安全性.本文主要介绍python应用(django)跑在docker容器里,编写dockerfil ...

  7. JavaWeb学习 (二十五)————监听器(Listener)

    一.监听器介绍 1.1.监听器的概念

  8. MySQL之单表查询

    一.关键字的执行优先级 1,from:找到表 2,where:拿着where指定的约束条件,去文件/表中取出一条条数据 3,group by:将取出的一条条数据进行分组,如果没有group by,则整 ...

  9. .net MVC使用Session验证用户登录(转载)

    .net MVC使用Session验证用户登录   用最简单的Session方式记录用户登录状态 1.添加DefaultController控制器,重写OnActionExecuting方法,每次访问 ...

  10. blfs(systemd版本)学习笔记-编译安装sudo并创建普通用户配置sudo权限

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! blfs书中sudo的安装配置章节:http://www.linuxfromscratch.org/blfs/view/stab ...