JavaScript高级程序设计:6.7.8章阅读札记

来源:互联网 发布:sql脚本编写教程 编辑:程序博客网 时间:2024/05/17 22:23

第六章 :对象

6.1 对象的属性

对象的属性分为两类:数据属性、访问器属性

A: 数据属性

  • configurable(能否通过delete删除属性从而重新定义属性)
  • enumerable(是否可通过for…in枚举属性)
  • writable(是否可修改,为false时,修改属性值将无效,严格模式修改下会报错)
  • value(属性对应的值)

B、访问器属性:(设置使用访问器属性的值一般会属性其他属性发生变化)

  • configurable(能否通过delete删除属性从而重新定义属性)
  • enumerable(是否可通过for…in枚举属性)
  • get(读取属性时调用的函数。默认值为undefined)
  • set(设置属性时调用的函数。默认值为undefined)
var book={    _year: 2004, //_用于表示只能通过对象特权方法来访问的私有属性    edition:1}Object.defineProperty(book,'year',function(){    get: function(){        return this._year    },    set: function(newValue){    if(newValue>2004){        this._year = newValue;        this.edition + = newValue - 2004;    }    }})book.year = 2005; //set新值为2005console.lot(book);//_year: 2005,edition:2,year:2005

注意:当只指定getter意味着属性是不能写的,尝试写入属性会被忽略,在严格模式下写入只有getter函数的属性会抛出错误。

6.2 同时定义多个属性的方法:
Object.defineProperties(obj,{    "property1":{value:1},    "property2":{value:2}})Object.getOwnPropertyDescriptor(obj,"propertyName"); //读取对象的某一属性
6.3 创建对象的几种方式衍变
1、工厂函数模式

特点:在函数内部创建了新对象,并最终返回该对象
缺点:没有解决对象识别的问题,即不知道对象的类型,无法通过instanceof来判断对象是否是该函数的实例

function parent(name,age,job){    var o = new Object(); //1、函数内部创建了一个新对象    o.name = name;    o.age = age;    o.job = job;    return o; //2、返回了对象}var child = person('jack',18,'engineer') //3、通过调用函数的方式创建对象console.log(child instanceof parent) //false
2、构造函数模式

特点:构造函数本身也是函数,但首字母大写;通过new 来创建对象
缺点:函数内的所有方法和属性都会copy到实例中,即同一个作用的方法在不同实例中,创建了很多次,千万资源浪费

function Parent(name,age,job){ //1、首字母大写表示构造函数    this.name = name; //2、直接将属性和方法赋给了this    this.age = age;    this.job = job;    this.sayName = function () { //3、生成实例时会创建很多次        console.log(this.name)    }}//3、通过new 创建实例,this自动指向创建的对象实例var child = new Parent('rose',18,'dancer')//4、可能通过instanceof检测对象的实例类型console.log(child instanceof Parent) //true
3、原型模式

特点:为避免创建实例对象时总是重复创建相同功能的方法,而将共有方法写在property对象上
缺点:所有属性和方法都在原型对象上,导致一个实例如果修改原型上的引用类型数据,则其他实例对应该原型属性的值也会被修改

    function Parent () {}    Parent.prototype.name = 'all'    Parent.prototype.age = 18    Parent.prototype.job = 'FE'    var child = new Parent()    console.log('name' in child)//true,通过in操作符判断对象实例child是否有name属性,不区分原型还是实有属性    console.log(child.hasOwnProperty('name'))//false,判断name是否为child的实有属性
4、构造函数和原型组合模式

在前几种的优点上进行综合。特点:对每个实例特有的可修改属性用this.name的方式定义,对共享的方法属性用prototype来定义
缺点,原型上的方法都写在了构造函数之外

function Parent(name){this.name = name //每个实例都特有的属性,修改不影响其他实例}Parent.prototype.sayName = function(){    console.log(this.name)}var child = new Person();
5、动态原型模式

说明:使用动态原型模式时,不能使用对象字面量重写原型。
附: Object.isPrototypeOf(obj) 查看一个属性是否是一个对象的原型链上的属性
特点:通过if判断构造函数是否已经初始化过了,从而避免重复执行初始化

function Parent() {    this.name = 'hello' //属性    //检查其中一个初始化之后就应该存在的任何属性和方法,如果不存在,则初始化它。    if(Parent.prototype.sayName !== 'function'){    Parent.prototype.sayName = function(){    console.log(this.name)    }    Parent.prototype.sayHello = function(){    console.log('hello')    }}}

注意:if中的原型属性或方法只需选择任意一个只要在初始化之后就存在的就好了,不需要重复判断

6.4、原型链式继承

特点:将要实现继承的构造函数的原型用父构造函数的实例替换而实现。
注意:
A、添加新的原型方法的代码一定要放在用父实例替换原型的语句之后
B、不能用对象字面量的形式重写原型,这样原型是被重写了,就没有指向Parent的原型了

function Parent(){    this.name = 'sophie'}Parent.prototype.say = function(){    console.log(this.name)}functin Child(){    this.childName = 'box'}Child.prototype = new Parent() //原型继承Child.prototype.sayChild = function(){ //在原型上添加新方法    console.log(this.childName)}var child = new Child()child.say(); //调用原型链上的方法

问题:父构造函数上的引用类型的属性指向了多个实例,改变其一,就都改变了(引用类型按引用传递数据)
如下:

function Parent(){    this.colors = ['red','blue','green']}function Child(){}Child.prototype = new Parent()var child = new Child()child.colors.push("black")//如下引用类型的原型属性被一个实例修改了,其他实例属性也被同时修改console.log(child.colors)//['red','blue','green','black']var child2 = new Child()console.log(child2.colors) //['red','blue','green','black']

解决方案: 使用借调构造函数及原型链方式组合继承 (在构造函数内使用apply(),call())
特点:解决方案: 使用借调构造函数及原型链方式组合继承 (在构造函数内使用apply(),call())
附:apply(),call()的区别,它们都可以用于将一个方法应用到传入的对象上,实现方法的借调,区别:apply传入参数为数组,call传入参数为单个逗号隔开
4、在JS中(ES5)没有块级作用域,因此通过(function(){})()立即执行匿名函数的方式来临时创建一个私有作用域

5、JS中的私有变量

说明: 在对象中是没有私有成员的概念的,但有时候需要隐藏对象内一些不应该被直接修改的数据时可以通过私有变量的形式来避免
缺点:必须使用构造函数模式来实现私有变量。而构造函数模式会针对每个实例创建同样一组新方法

function Person(name){    //私有属性和方法    var hehe  = name    function sayName(){        console.log(hehe)    }    //特权方法,供外部调用    this.getAll = function(){        sayName()    }}var p = new Person('hello')console.log(p.sayName) //undefinedconsole.log(p.getAll) //'function',只有通过getAll这一个接口来调用内部方法
6、单例

singleton:指只有一个实例的对象。在web应用程序中,经常需要使用一个来管理应用程序级的信息。

七、BOM

不同浏览器对BOM的实现有些差别,在浏览器中可以将window看作是全局Global。而window下又包含几大属性:location,navigator,screen,history

7.1 location对象 —— 常用于url相关操作

location.hash :返回或设置hash值 #contents
location.host: 返回服务器名称和端口号
www.wrox.com:8
location.hostname: 返回不带端口号的服务器名称 www.wrox.com
location.href : 完整URL “http:/www.wrox.com
location.pathname : 目录或文件名部分 /WileyCDA/
location.port :端口号 8080
location.protocol :协议 http:
location.search :查询字符串 ?q=javascript

7.2 navigator对象——常用于检测网页的浏览器类型

userAgent : 保存着当前浏览器的信息

7.3 history对象 ——保存着用户上网的历史记录,从容器被打开的那一刻算起。

go() :跳转到指定页面,接收数字或url作为参数
back() :返回一页,相当于go(-1)
forward() : 前进一页,相当于go(1)
length: 返回访问过的页面的数据

7.4 screen对象 —— 提供了操作浏览器窗口的api

creen.availWidth - 可用的屏幕宽度
screen.availHeight - 可用的屏幕高度

7.5 iframe

每个iframe都相当于一个浏览器窗口,其都包含各自的window对象
top: 对象始终指向最外围的框架,即整个浏览器容器
parent:指向当前iframe的父窗口
self:指向当前iframe的window

原创粉丝点击