Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)

var obj = {‘a‘:‘a‘};
var fun = function (){}
console.log(typeof obj);//object
console.log(typeof fun);//function
var a;
console.log(a === undefined);//true
console.log(typeof b);//true 未声明的变量使用会报错,但是他的typeof=undefined
var c=null;
console.log(typeof c);//object null是对象的空指针,如果声明变量将要保存的数据类型是object,那么初始化该变量的时候设置为null
console.log(null == undefined);//true undefined的值派生与null
var message = ‘hello word‘;
var messageBoolean = Boolean(message);
console.log(messageBoolean);//true  把变量转换成boolean值
var num1 = 070,//56   0~7
    num2 = 0xA;//10   0~9 A~F
console.log(num1);//56 八进制数值
console.log(num2);//10 十进制数值
var sum = 0.1+0.2;
console.log(sum);//0.30000000000000004
var maxNum = Number.MAX_VALUE;
console.log(maxNum);//js 在一般浏览器中所能存储的最大值
var minNum = Number.MIN_VALUE;
console.log(minNum);//js 在一般浏览器中所能存储的最小值
var test = "this is the letter singma: \u03a3.";
console.log(test);

//object
var o = new Object();
o.name = ‘tome‘;
console.log(o.hasOwnProperty(‘name‘));//检查name属性是否存在o对象中
var numa = 10,//怎么正确理解前置操作和后置操作:1、操作的是变量;2、表达式运算    前置操作是先改变变量的值然后再进行表达式运算,后置操作是先进行表达式运算然后再改变变量的值;谨记变量的值在后期的运算中已经改变
    numb = 15;
var numc = ++numa + numb--;
console.log(numa);//11
console.log(numb);//14
console.log(numc);//26
console.log(numa+numb);//25
(function(){ console.log(‘this is a function‘);})();//匿名函数的调用方式
var somevar = false;//根据该值判断逻辑与的短路操作,逻辑或也是短路操作
var result = (somevar && undefinedvar);
console.log(result);
var n = 5+‘5‘;
console.log(n);//55
console.log(‘--------------------------------‘);
for(var proName in window){//for(var name in object){} 循环对象中的属性
//    console.log(proName);
}
var num = 0;
outermost://label 语句在循环中使用continue和break时判断退出到哪层循环,正常情况下break只会退出一层循环
for (var i=0; i<10; i++){
    for (var j=0; j<10; j++){
        if(i == 5 && j == 5){
            break outermost;
        }
        //console.log(i+‘---‘+j);
    }
}
function sayHi(){
    console.log(arguments);//在函数内部中使用arguments获取参数的数组  arguments.length获取参数的个数
}
sayHi(‘a‘);
//函数的参数可以传object
function setName(obj){
    obj.name = "Nicholas"
}
var person = new Object();
setName(person);
console.log(person.name);
console.log(person instanceof Object);//person是对象吗
console.log(person instanceof Array);//person是数组吗
console.log(person instanceof RegExp);//person是正则表达式吗

function add(n1,n2){
    summ = n1 + n2;//有var会报错,因为var声明的变量是在当前作用域链下,如果没有var则是全局变量隶属于window(不声明直接赋值的做法不可取)
    return summ ;
}
add(1,2);
console.log(summ);//如果有var声明summ会报错
console.log(window.summ);//如果没用var声明变量则可以在window对象中找到该属性
var color = new Array(3);
var color = new Array(‘three‘);
console.log(color);//注意区分输出结果
//在数组后面追加元素
var color = [‘red‘,‘blue‘,‘green‘];
color[color.length] = ‘black‘;
console.log(color);//["red", "blue", "green", "black"]
console.log(color instanceof Array);//true 数组检测
console.log(Array.isArray(color));//true 数组检测
console.log(color.toString());//数组转换成字符串,以逗号分隔
console.log(color.join("||"));//red||blue||green||black
//对象中定义成员方法
var people = {
    p:function(){
        return ‘abc‘;
    }
}
console.log(people.p());
//数组排序
var values = [0,1,5,10,15];
console.log(values.sort(compare));
function compare(value1,value2){
    /*if(value1 < value2){
        return -1;
    }else if(value1 > value2){
        return 1;
    }else{
        return 0;
    }或者*/
    return value1 - value2;
}
//数组迭代方法
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item,index,array){//判断数组中的元素是否都大于2(数组判断)
    return (item > 2);
});
console.log(everyResult);//false
var someResult = numbers.some(function(item,index,array){//判断数组中的元素是否有大于2的 (数组判断)
    return (item >2 );
})
console.log(someResult);//true
var filterResult = numbers.filter(function(item,index,array){//返回数组中大于2的元素(数组过滤)
    return (item > 2);
});
console.log(filterResult);//[3, 4, 5, 4, 3]
var mapResult = numbers.map(function(item,index,array){//数组中的每一项都乘以2(数组运算)
    return (item * 2);
});
console.log(mapResult);//[2, 4, 6, 8, 10, 8, 6, 4, 2]
numbers.forEach(function(item,index,array){//数组的遍历     value/key/array
    console.log(item);
});
console.log(‘-----------‘);
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev,cur,index,array){
    return prev + cur;
});
console.log(sum);//数组求和
//正则表达式
var text = "cat, bat, sat, fat";
var pattern1 = /.at/g;//g 注意g对matches的影响
console.log(pattern1.test(text));//true 在text中匹配pattern1
var matches = pattern1.exec(text);
console.log(matches);
/**
 * 函数
 */
function func(num1,num2){
    console.log(num1 + num2);
}
anotherFun = func;//函数名就是函数对象的指针(注意有括号和无括号的区别)
anotherFun(10,10);
if(true){//函数作为参数传递
    function callSomeFunction(someFunction,someArguments){
        return someFunction(someArguments);
    }
    function add10(num){
        return num + 10;
    }
    console.log(callSomeFunction(add10,10));//20
}
//数组中按照对象属性的值进行排序
function createComarisonFunction(propertyName){
    return function(object1,object2){//sort函数会自动传递过来两个参数
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        if(value1 < value2){
            return -1;
        }else if(value1 > value2){
            return 1;
        }else{
            return 0;
        }
    }
}
var data = [{name:‘Zachary‘,age:28},{name:‘Nicholas‘,age:29}];
data.sort(createComarisonFunction("name"));
console.log(data);//[{name:‘Nicholas‘,age:29},{name:‘Zachary‘,age:28}]
data.sort(createComarisonFunction(‘age‘));
console.log(data);//[{name:‘Zachary‘,age:28},{name:‘Nicholas‘,age:29}]
//函数内部属性this:全局对象,arguments:参数数组,arguments.callee:该函数,arguments.callee.caller:该函数的引用(也就是哪个函数中调用了这个函数)
function factorial(num){
    console.log(arguments.callee);//arguments.callee 指向该函数
}
factorial();

function outer(){
    inner();
}
function inner(){
    console.log(arguments.callee.caller);//function outer(){inner();}显示当前函数的引用函数(也就是哪个函数引用了这个函数)
}
outer();
//函数外部属性length:参数的个数,prototype
function sayName(name){
    return ‘‘;
}
console.log(sayName.length);//1 函数参数的个数
console.log(sayName.prototype);//空对象 toString()和valueOf()的方法实际上都保存在prototype名下
//函数方法:call,apply,bind方法         指定函数运行的作用域(谨记作用域链的概念)
window.color = ‘red‘;
var o = {color:‘blue‘};
function sayColor(){
    return this.color;
}
console.log(sayColor.call(window));//red   在window环境下运行sayColor方法
console.log(sayColor.call(o));//blue    在o对象环境下运行sayColor方法
var objectSayColor = sayColor.bind(o);//把sayColor绑定到o对象里面
console.log(objectSayColor());//blue

var s1 = "some text";
var s2 = s1.substring();
console.log(s2);

var num = 10;
console.log(num.toFixed(2));//10.00
var text = "cat, bat, sat, fat";
var parttern = /.at/;
console.log(text.match(parttern));
/**
 * 对象 object
 */
//对象中属性的特性:数据属性和访问器属性,数据属性包含(configurable:属性是否可删除  enumerable:属性是否可以用for-in遍历  writable:属性是否可以重写  value:属性设置的值),访问器属性包含get和set方法,访问器属性的常见用法是在设置一个属性的时候会让其他属性也发生变化
//数据属性
var person = {};
Object.defineProperty(person,"name",{//如果这样去设置对象中的属性,那么未设置的特性均为false
    writable:false,//该属性的值不可以修改(只读)
    enumerable:false,//是否可以使用for in遍历属性
    configurable:true,//是否可以删除属性,是否可以把数据属性修改为访问器属性
    value:‘Nicholas‘//设置值
});
console.log(person.name);//Nicholas
person.name = "Greg";//设置无效,在严格模式下会报错
console.log(person.name);//Nicholas
//访问器属性:通过设置对象的一个属性的值,会导致其他属性发生变化,这就是访问器属性的常用方法
var book = {
    _year:2004,
    edition:1
};
Object.defineProperty(book,"year",{
    get:function(){
        return this._year;
    },
    set:function(newValue){
        if(newValue > 2004){
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
});
book.year = 2005;//设置year的值会改变其他两个属性的值
console.log(book.edition);
//同时设置数据属性和访问器属性
var book = {};
Object.defineProperties(book,{
    _year:{//数据属性
        writable:true,
        value:2004
    },
    edition:{//数据属性
        writable:true,
        value:1
    },
    year:{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue > 2004){
                this._year = newValue;
                this.edition += newValue - 2004;
            }
        }
    }
});
book.year = 2005;//设置year的值会改变其他两个属性的值
console.log(book);
//读取属性的特性
var descriptor = Object.getOwnPropertyDescriptor(book,"_year");//读取_year属性的特性
console.log(descriptor.value);//2005
console.log(descriptor.configurable);//false 由于_year属性的configurable特性未设置,因此返回false
/**
 * 对象设计模式
 */
//1、构造函数模式(工厂模式实用性比较差)
/* function Person(name,age,job){//构造函数
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        return this.name;
    }
}
var person1 = new Person(‘Nicholas‘,29,"Software Engineer");//该步骤经历四个过程:1、person1 = {};2、Person.call(person1);构造函数的作用域赋值到对象3、执行函数中的代码;4、返回新对象
var person2 = new Person("Greg",27,"Doctor");
console.log(person1.name);//Nicholas
console.log(person2.name);//Greg
console.log(person1.sayName());//Nicholas */
/**总结**/
// 可以把构造函数看做是一个类,但是构造函数有一个缺点,就是包含方法的构造函数每实例化一个构造函数就会创建一个方法,即便是实现同样功能的方法也会在实例化构造函数的时候创建多个,可以通过以下方式来解决.如:
/* function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName(){
    return this.name;
}
var person1 = new Person("Nicholas",29,"Softwar Engineer");
console.log(person1.sayName());//Nicholas */
//以上方法可以达到在实例化构造函数的时候不会创建多个函数(方法),但是这样就失去了封装性的意义

//2、原型模式:优点属性共享 缺点也是属性共享 因此就出现了
/* function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    return this.name;
}
var person1 = new Person();
console.log(person1.name);
console.log(Person.prototype.isPrototypeOf(person1));//true person1是Person的实例吗
console.log(Object.getPrototypeOf(person1));//Person.prototype  获取person1构造函数的原型对象
console.log(person1.hasOwnProperty("name"));//false   person1中是否有name属性,Person.prototype中的name属性不算
console.log("name" in person1);//true name属性是在person1实例中吗? 无论name属性是实例属性还是原型属性都可以取得到
person1.name = "Greg";
console.log("name" in person1);//ture name属性是实例中的属性
console.log(person.hasOwnProperty("name"));//ture
function hasPrototypeProperty(obj,name){//判断属性是否是原型中的属性
    return (name in obj) && !obj.hasOwnProperty(name);
}
console.log(hasPrototypeProperty(person1,"name"));//false  因为name属性不是原型属性而是实例属性
delete person1.name;
console.log(hasPrototypeProperty(person1,"name"));//true  此刻的那么属性是原型中的属性
//枚举属性(遍历属性)
var o = {
    toString:function(){
        return "My Object";
    },
    name:"Nicholas"
};
for(var prop in o){//遍历实例对象中的所有属性
    console.log(o[prop]);
}
for(var pro in Person.prototype){//遍历原型对象中的所有属性
    console.log(Person.prototype[pro]);
}
console.log(Object.keys(Person.prototype));//获取原型对象中的所有属性
console.log(Object.keys(person1));//获取实例对象中的所有属性
console.log(Object.getOwnPropertyNames(Person.prototype));//获取对象中的所有属性包括不可枚举的constructor
console.log(Array.prototype); */
//3、构造函数模式和原型模式的组合方式(对象设计模式的终极解决方案)
/* function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby","Court"];
}
Person.prototype = {
    constructor:Person,
    sayName:function(){
        return this.name;
    }
};
var person1 = new Person("Nichlas",19,"Software Engineer");
var person2 = new Person("Greg",27,"Doctor");
person1.friends.push("Van");
console.log(person1.friends);//["Shelby", "Court", "Van"]
console.log(person2.friends);//["Shelby", "Court"] */
//4、动态原型模式(弥补了构造函数模式中函数多次创建的问题)类似于上面构造函数中"总结"部分中的变种
/* function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            return this.name;
        }
    }
}
var person1 = new Person("Nicholas",29,"Software Engineer");
console.log(person1.sayName()); */
//5、继承(原型链的继承:实际应用中很少使用)
/* function SuperType(){//父构造函数
    this.property = true;//构造函数模式定义属性
    this.abc = ‘abc‘;
}
SuperType.prototype.getSuperValue = function(){//父原型对象中添加一个方法
    return this.property;
}
function SubType(){//子构造函数
    this.subproperty = false;//构造函数模式定义属性
}
SubType.prototype = new SuperType();//子原型对象继承父实例
SubType.prototype.getSubValue = function(){//字原型中添加一个方法
    return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue());//true 实现了继承
console.log(instance.abc);//abc 实现了继承
console.log(instance.getSubValue());//false 子类型中的方法(非继承)
console.log(instance instanceof Object);//true instance实例是指向Object对象的原型吗
console.log(instance instanceof SuperType);//true instance实例是指向SuperType的原型吗
console.log(instance instanceof SubType);//true instance实例是指向SubType的原型吗
console.log(Object.prototype.isPrototypeOf(instance));//true 同上
console.log(SuperType.prototype.isPrototypeOf(instance));//true 同上
console.log(SubType.prototype.isPrototypeOf(instance));//true  同上 */
//6、借用构造函数实现继承(现实中很少单独使用)
/* function SuperType(){//父构造函数
    this.color = ["red","blue","green"];
}
function SubType(){//子构造函数
    SuperType.call(this);//在该函数作用域下执行SuperType方法  (在子构造函数中借用父构造函数)
}
var instance1 = new SubType();
instance1.color.push("black");
console.log(instance1.color);//"red", "blue", "green", "black"]
var instance2 = new SubType();
console.log(instance2.color);//["red", "blue", "green"] */
//7、组合继承(最常用)缺点是调用2次SuperType构造函数优化方式为寄生组合式继承(10)
/* function SuperType(name){
    this.name = name;
    this.colors = [‘red‘,‘blue‘,‘green‘];
}
SuperType.prototype.sayName = function(){
    return this.name;
}
function SubType(name,age){
    SuperType.call(this,name);
    this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    return this.age;
}
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("block");//通过借用构造函数继承进行修改属性
console.log(instance1.colors);//["red", "blue", "green", "block"]  通过借用构造函数继承取值
console.log(instance1.sayName());//Nicholas 通过原型链继承方式调用到父构造函数中的原型对象中的方法
console.log(instance1.sayAge());//29 调用子构造函数中原型对象中的方法

var instance2 = new SubType("Greg",27);
console.log(instance2.colors);//["red", "blue", "green"]
console.log(instance2.sayName());//Greg 其实是又new 了一个父构造函数
console.log(instance2.sayAge());//27 */
//8、原型式继承(在没有必要兴师动众的创造构造函数的情况下使用该继承)
/* var person = {
    name:"Nicholas",
    friends:["shelby","Court","Van"]
};
var anotherPerson = Object.create(person);
console.log(anotherPerson.name);//Nicholas 对象的复制
var yetanotherPerson = Object.create(person,{//重定义属性
    name:{
        value:"Greg"
    }
})
console.log(yetanotherPerson.name);//Greg */
//9、寄生式继承(继承父类的时候可以添加自己的属性方法)函数不能复用,因此效率比较低下
/* function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
function createAnother(original){
    var clone = object(original);
    clone.sayHi = function(){
        console.log("Hi");
    };
    clone.age = 29;
    return clone;
}
var person = {
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//Hi
console.log(anotherPerson.age);//29 */
//10、寄生组合式继承(最理想的继承方式)
function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
function inheritPrototype(subType,superType){
    var prototype = object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
function SuperType(name){
    this.name = name;
    this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
    return this.name;
}
function SubType(name,age){
    SuperType.call(this,name);
    this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
    return this.age;
};
var instance1 = new SubType("Nicholas",29);
console.log(instance1.name);//Nicholas
console.log(instance1.age);//29
console.log(instance1.sayName());//Nicholas
console.log(instance1.sayAge());//29
时间: 2024-10-22 09:33:51

Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)的相关文章

javascript高级程序设计——笔记

javascript高级程序设计--笔记 基本概念 基本数据类型包括Undefined/Null/Boolean/Number和String 无须指定函数的返回值,实际上,未指定返回值的函数返回的是一个特殊的undefined值 变量.作用域和内存问题 基本类型值在内存中占据固定大小的空间,因此保存在栈内存中 引用类型的值是对象,保存在堆内存中 确定一个值是哪种基本类型用typeof,确定一个值是哪种引用用instanceof 所有变量都存在于一个执行环境当中,这个执行环境决定了变量的生命周期,

javascript高级程序设计笔记1

最近在看javascript高级程序设计,看之前觉得自己的js学得还不错,然后,看了没几页就觉得自己好像没有学过一样,这主要写写我以前不完全了解的一些知识. 首先是关于基本数据类型的,从Number开始,以前经常用parseInt来转换数值,看过书才知道,这个函数的本意是专门用于把字符串转换成数值,而且以前也不知道它具体是怎么一个转换规则.先来看看Number()函数的转换规则: 1.如果是Boolean 值,true 和false 将分别被转换为1 和0.2.如果是数字值,只是简单的传入和返回

【javascript高级程序设计笔记】第六章OOP

忙了一段时间,加了将近一个月的班. 书也落下没看,上次看到第七章(这部分笔记大概还是9月份的吧),偶尔看到很吃力.看的速度慢下来. 学习就是一个慢慢积累慢慢沉淀的过程.看书时没有明显觉得提升.但在看完书后近段时间工作中写代码,明显感觉效率还是有提升,基础知识牢固了. 这本书是第二次看,这次很认真的遍读和做笔记,笔记的文字均是自己边看边敲的,这样才更好的真正的吸收到一部分吧! 这些天在看web响应式设计:HTML5和CSS3实战 第6章 面向对像的程序设计 6.1.1属性类型 ECMAScript

javascript高级程序设计笔记(第5章 引用类型)

1.Object类型 两种方式定义:对象字面量.new 两种方式访问:括号.点 2.Array类型 2.1  定义方式:new Array.数组字面量 2.2  lenght属性:可以利用它方便的想数组末尾添加元素 2.3  检测数组 instanceof isArray()方法  2.4  toString().soLocaleString().valueOf().join()方法 2.5.栈方法   push()方法:逐个添加到数组末尾,并返回修改后的数组长度 pop()方法:返回数组的最后

JavaScript高级程序设计笔记之面向对象

说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,JavaScript中如何面向对象? JavaScript中将对象定义为:一组无序的 键值对的集合,属性以及方法的名称就是键,键的值可以是任何类型(字符串,数字,函数--) 在JavaScript中,所有对象继承自Object,所有对象继承自Object,所有对象继承自Object! 创建 1  简单创建

【javascript高级程序设计笔记】第一章与第三章

第1章 javascript简介 1.2Javascript实现 一个完整的javascript实现由下列三个不同的部分组成 核心(ECMAScript) 提供核心语言功能 文档对象模型(DOM) 提供访问和操作网页内容的方法和接口 浏览器对象模型(BOM)提供与浏览器交互的方法和接口 ECMAScript 它规定了这门语言的下列组成部分: 语法  类型  语句  关键字 保留字 操作符 对象 ECMA-262第5版,发布于2009年. 文档对象模型(DOM) Document Object M

javascript高级程序设计笔记(第7章 函数表达式)

7.5 小结 在JavaScript 编程中,函数表达式是一种非常有用的技术.使用函数表达式可以无须对函数命名,从而实现动态编程.匿名函数,也称为拉姆达函数,是一种使用JavaScript 函数的强大方式.以下总结了函数表达式的特点.? 函数表达式不同于函数声明.函数声明要求有名字,但函数表达式不需要.没有名字的函数表达式也叫做匿名函数.? 在无法确定如何引用函数的情况下,递归函数就会变得比较复杂:? 递归函数应该始终使用arguments.callee 来递归地调用自身,不要使用函数名——函数

javascript高级程序设计笔记2

继续之前的,改说到object类型的了:Object 的每个实例都具有下列属性和方法. constructor:保存着用于创建当前对象的函数.对于前面的例子而言,构造函数(constructor)就是Object(). hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在.其中,作为参数的属性名(propertyName)必须以字符串形式指定(例如:o.hasOwnProperty("name")). isProt

JavaScript高级程序设计笔记

1.1 JavaScript简史 <script> async/defer可以控制js加载顺序 把js文件放在页面底部,加快页面打开速度 3 基本概念 语法 数据类型 流控制语句 理解函数 3.4 数据类型 ECMAScript中定义了六种数据类型:Underfined.Null.Boolean.Number.String.Object 使用typeof关键字来检测类型 //Boolean()转换 var bool1 = Boolean(true); var bool2 = Boolean(&