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);//
console.log(numb);//
console.log(numc);//
console.log(numa+numb);//
(function(){ console.log('this is a function');})();//匿名函数的调用方式
var somevar = false;//根据该值判断逻辑与的短路操作,逻辑或也是短路操作
var result = (somevar && undefinedvar);
console.log(result);
var n = 5+'5';
console.log(n);//
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);//
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);//
console.log(instance1.sayName());//Nicholas
console.log(instance1.sayAge());//
Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)的更多相关文章
- JavaScript高级程序设计笔记之面向对象
说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...
- JavaScript高级程序设计笔记(一)
---恢复内容开始--- 前三章为基础知识,为了方便以后查看,所以比较啰嗦.这里对函数的基本操作没有记录. 1.JavaScript的实现 虽然 JavaScript 和 ECMAScript 通常都 ...
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...
- javascript高级程序设计--笔记01
概述 JavaScript的实现包含三个部分: 1 核心(ECMAScript) 提供核心语言功能 2 文档对象模型(DOM) 一套提供了访问以及操作网页内容的API 3 浏览器对象模型( ...
- javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记
1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...
- <javascript高级程序设计>笔记
1.要讲一个值转换成其对应的Boolean类型 ,可以调用转型函数Boolean(). var message=“hello world!”; var messageAsBoolean=Boolean ...
- javaScript高级程序设计笔记 2
Undefinde Null Boolean Number String 基本类型 Object 引用类型 只有引用类型才能动态的添加属性 赋值基本类型和引用类型也不相同,复制的基本类型的 ...
- javaScript高级程序设计笔记 1
核心 ECMAScript 文档对象模型 DOM 浏览器对象模型 BOM 延迟脚本 defer typeof操作符 判断字符类型 返回 undefined boolean s ...
- Javascript高级程序设计笔记 <第五章> 引用类型
一.object类型 创建object实例的方式有两种: //第一种使用new操作符跟构造函数 var person= new Object(); person.name="小王" ...
随机推荐
- Jackson对泛型的序列化和反序列化方法汇总
说明:Jackson对于简单泛型是可以正常操作的,但是如果对于太过于复杂的泛型类有时会不成功.目前还在找着更合适的Json库.不过这一点在dotnet原生方案JavaScriptSerializer可 ...
- js/jq仿window文件夹框选操作插件
0.先给大家看看效果: 1.创建一个index.html文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...
- HTML5 一些有用的 APIs
Animation Timing Window.requestAnimationFrame(callback): 告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘(类似于 setTi ...
- xcode创建一个工程的多个taget,便于测试和发布多个版本
背景:很多时候,我们需要在一个工程中创立多个target,也就是说我们希望同一份代码可以创建两个应用,放到模拟器或者真机上,或者是,我们平时有N多人合作开发,当测试的时候,在A这里装了一遍测A写的那块 ...
- 【Exception】查看异常出现在具体的文件名/类名/方法名/具体行号
今天在处理异常日志保存过程中,想要获取到异常抛出在具体在那个文件,哪个类下的哪个方法中的具体第几行,所以具体实现如下 try{ Integer adminID = Integer.parseInt(a ...
- CA认证原理以及实现(下)
在上述的文章后了解到原理之后,我们这篇文章来进行CA的搭建. OPEN SSL 环境搭建在基础原理中我们提到了两种认证服务,单项认证服务和双向认证服务,我们就以双向认证服务举例说明.OpenSSL是一 ...
- ccs 中的定位
一.相对定位 position:relative; 作用: 相对定位 一般加给定位元素父级 特点: (1)不脱离文档流: (2)不改变元素类型: (3)参照物是元素本身: 二.绝对定位 posi ...
- Mysql5.6审计功能
1. 前言 为了安全和操作的可追溯性考虑,越来越多的公司增加了审计功能.mysql5.5推出了相关的审计功能,到5.6.20功能进一步完好.算是勉强可用了.尽管细粒度方面做的不是太好. ...
- 百科知识 kux文件如何打开
即使是官方自带的浏览器也无法打开 你可以直接复制文件名 然后在百度里搜即可 你自己下载的东西还是能转码的
- ggplot2-为图形加入直线
本文更新地址:http://blog.csdn.net/tanzuozhev/article/details/51112057 本文在 http://www.cookbook-r.com/Graphs ...