JSLearning
标签(空格分隔): 前端学习
基础
值类型
- Undefine
- Null
- Boolean
- Number
- String
引用类型
- Object
Object支持动态创建属性
var person = new Object();
person.name = "Hello JavaScript";
alert(person .name);
检测类型
var s = "Nicholas" ;
alert(typeof s); //string
person = new Object ();
alert(person instanceof Object );//true
RegExp
var expression1 = /[bc]at/i
var expression2 = new ReqExp("[bc]at","i");
正则表达式字符串匹配元字符以及已经转义过的字符需要双重转义
元字符:( [ { \ ^ $ | ) ? * + . ] }需要转义成
"\\["
等
已转义的字符:\n \ 需要转义成"\\n" "\\\\"
Function
函数本质上一个对象,是Function类型的实例。
//函数声明
function sum (num1,num2) {
return num1 + num2;
}
//函数表达式
var sum = function(num1, num2) {
return num1 + num2;
}
var sum = new Function("num1","num2","return num1 + num2");//不推荐
//这三种都是定义一个函数,但是sum可以改变的,仅仅是一个指针
没有重载的概念
函数声明和函数表达式的区别
解析器在加载数据的时候,会率先读取函数声明,并使其在执行任何代码之前可用;治愈函数表达式,则必须等解析器执行到它所在的代码行,才会被真正正确的解释执行。
alert(sum(10,10));
function sum (num1,num2) {
return num1 + num2;
}
//以上代码ok
alert(sum(10,10));
var sum = function(num1, num2) {
return num1 + num2;
}
//以上代码error
函数可以当参数,也可以当返回值
函数的内部属性
*arguments(传入函数的所有参数)
*arguments.callee(正在被执行的函数对象)
*arguments.callee.caller(当前函数的调用方)
*this(执行的环境对象,网页的全局域中调用的时候,this就是window,如果作为一个对象的属性调用,比如o.sum(10,10),this就是o这个对象)
函数属性和方法
*length 参数的数量
*prototype
*call,apply 设定函数的作用域,即this的值
*bind 绑定函数的作用域,即this的值
基本的包装类型
特殊的引用类型
*Boolean
*Number
*String
面向对象基础
对象是无序属性的集合,其属性可以包含基本值、对象或者函数。
//对象定义
var person = {
name:"Nicholas",
age:29,
job:"Software Engineer",
sayName:function(){
alert(this.name);
}
}
数据属性
- Configurable:是否可以通过delete删除属性
- Enumerable:是否可以通过for-in循环返回属性
- Writable:是否可写
- Value:属性的数据值
对象直接定义和通过
defineProperty
定义属性的时候以上的各个值默认值不一样,前者都是true,后者都是false,但value都是undefine。
访问器属性
- Configurable
- Enumerable
- Get 读取属性时调用的函数
- Set 写入时调用的函数
对象直接定义和通过
defineProperty
定义属性的时候以上的各个值默认值不一样,前者都是true,后者都是false,但get & set 都是undefine。
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;
alert(bool.edition)
读取属性的特性
Object.getOwnPropertyDescriptor
创建对象
工厂模式
function createPerson(name,age,job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
}
return o;
}
构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
}
}
var person1 = new Person("Greg",27,"Doctor");
//person1会有一个construtor(构造函数)属性 指向Person
使用new加构造函数创建实例会经历以下4个步骤
- 创建一个新的对象
- 将构造函数的作用域赋给对象(因此this指向了这个新对象)
- 执行构造函数中的代码(为这个对象添加属性)
- 返回新的对象
对象类型检测
alert(person1 instanceof Person);//true;
alert(person1 instanceof Object);//true
构造函数的问题
属性时函数对象的对象,会重复创建。
原型模式
每个函数都有一个prototype属性,是一个指针,指向一个对象,作用是让实例共享属性和方法。
原型对象的理解
function Person() {
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person();
person1.sayName();//访问原型对象的
- Person(函数对象)
- Peron.prototype(原型对象)
- person1(实例)
函数对象通过prototype属性访问原型对象,原型对象可以通过constructor对象访问函数对象,实例对象可以通过[[Prototype]]访问原型对象。
每当读取实例的某个属性的时候,都会执行一个搜索,首先搜索实例本身,然后沿着原型链搜索。
原型链:通过[Prototype]]属性连接起来,末端是Object.prototype
调用实例函数的时候,即使这个函数是原型对象定义,函数中的this依然指向当前实例
对象中新增一个和原型对象重名属性时,不会重写原型的值,而是新增一个属性,并屏蔽原型对象的属性
hasOwnProperty()
判断某个属性是否是实例属性。
!object.hasOwnProperty(name) && (name in object)
判断name是object原型对象的方法
原型的动态性
实例创建后修改原型,也能从实例中反映出来。
组合使用构造函数模式和原型模式
最常用的创建对象的方式
function Person(name,age,job) {
this.name = name;
this.age = age;
this.jog = job;
this.friends = ["shelby","court"];
}
Person.prototype.sayName = function() {
alert(this.name);
}
var person1 = new Person("Nicholas",29,"Doctor");
//实例属性在构造函数中定义,所有实例共享原型对象的属性,这个是默认模式
动态原型模式
function Person(name,age,job) {
this.name = name;
this.age = age;
this.jog = job;
if (typeof this.sayName != "function") {
Person.prototype.sayName = function() {
alert(this.name);
}
}
}
继承
原型链继承
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType() {
this.subProperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
//修复constructor
SubType.prototype.constructor = SubType;
SubType.prototype.getSubVale = function() {
return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());//true
以上代码最终形成这样的关系
SubType实例 -> SuperType实例(SubType.prototype) -> SuperType.prototype(Object实例) -> Object.prototype
SubType继承SuperType,SuperTyper继承Object
所有类型默认都继承Object类型,原因是默认原型都是Object的实例,指向了Object.prototype。
确定原型和实例的关系
alert(instance instanceof Object);//true
alert(instance instanceof SuperType);//true
alert(instance instanceof SubType);//true
给原型添加新方法,一定要放在替换原型语句之后
单纯的原型链问题:父类如果定义属性,被子类继承的时候,会被各个子类的实例共享,创建子类类型的时候,不能像父类传递属性。
构造函数继承
function SupetType(name) {
this.name = name;
}
function SubType() {
//继承了SuperType,同时还传递了参数
SuperType.call(this,"Nicholas");
//实例属性
this.age = 29;
}
var instance = new SubType();
alert(instance.name);//Nicholas;
alert(instance.age);//29
借用构造函数的问题:函数属性在构造函数内部定义,无复用,超类型原型中定义的方法,对子类不可见。
组合模式
最常用的继承方式
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
alert(this.name);
};
function SubType(name,age) {
//继承属性
SuperType.call(this,name);
//子类属性
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
//修正constructor
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
alert(this.age);
};
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
instance1.sayName();///Nicholas
instance1.sayAge();//29
var instance2 = new SubType("Greg",27);
alert(instance2.colors);//"red,bule,green"
instance2.sayName();//Greg
instance2.sayAge();//27
浅复制
var person = {
name:"Nicholas",
friends:["Shelby","Court","Van"]
}
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
//覆盖同名属性
var haAnotherPerson = Object.create(person,{
name:{
value:"Greg"
}});
alert(anotherPerson.name);//Greg
//这个函数的作用和Object.create传入一个参数时行为相同
function object(o) {
function F(){}
F.prototype = o;
return new F();
}
寄生组合式继承
最理想的继承范式
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
alert(this.name);
};
function SubType(name,age) {
//继承属性
SuperType.call(this,name);
//子类属性
this.age = age;
}
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;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function() {
alert(this.age);
};
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
instance1.sayName();///Nicholas
instance1.sayAge();//29
var instance2 = new SubType("Greg",27);
alert(instance2.colors);//"red,bule,green"
instance2.sayName();//Greg
instance2.sayAge();//27
函数表达式
//函数声明提升,调用可以放在声明前
sayHi();
function sayHi() {
alert("Hi!");
}
//函数表达式,错误,函数还不存在
sayHi();
var sayHi = function() {
alert("Hi!");
}
递归
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}
//命名函数表达式
var factorial = (function f(num) {
if (num <= 1) {
return 1;
} else {
return num * f(num-1);
}
})
闭包
类似于block,定义的时候可以引用外部变量,并持有。
function crateComparisonFunction(propertyName) {
return function(object1,object2) {
//引用了propertyName
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {u
retrn 0;
}
};
}
闭包和变量
function createFunctions() {
var result = new Array();
for (var i = 0;i < 10; i++) {
result[i] = function() {
return i;
}
}
//result数组中 每个函数变量i都是10 不是copy 只是引用
return result;
}
function createFunctions() {
var result = new Array();
for (var i = 0;i < 10;i++) {
result[i] = function(num){
return function() {
return num;
}
}(i);
}
//result数组中 每个函数的变量num就是从0到9
return result;
}
关于this
var name = "The Window";
var object = {
name:"My Object".
getNameFunc:function() {
return function() {
return this.name;
}
}
}
alert(object.getNameFunc()());//"The Window";
//这个调用和以上相同 所以this=window.
var f = object.getNameFunc();
alert(f();)
var name = "The Window";
var object = {
name:"My Object".
getNameFunc:function() {
var that = this;
return function() {
return that.name;
}
}
}
alert(object.getNameFunc()());//"My Object";
内存泄露
function assignHandler() {
var element = document.getElementById("someElement");
//循环引用
element.onclick = function() {
alert(element.id);
}
}
//破除循环引用
function assignHandler() {
var element = document.getElementById("someElement");
var id = element.id;
//循环引用
element.onclick = function() {
alert(id);
}
//局部变量设置为null,闭包也不会引用element,就不会循环引用了。
element = null;
}
闭包会引用包含函数的局部变量,即使没有直接引用局部变量,进而闭包会持有局部变量指向的对象,要破除这种持有,可以将局部变量设置为null在包含函数结束前。
模仿块级作用域
(function() {
//这里是块级作用域
})();
私有变量
funciton MyOject() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//特权方法
this.publicMethod = function() {
privateVariable++;
return privateFunction();
}
}
var object = new MyObject();
alert(object.publicMethod);
静态私有变量
(function() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//构造函数 未经声明的变量,会创建一个全局变量。
MyObject = function() {
};
//公有/特权方法
MyOject.prototype.publicMethod = function() {
privateVariable++;
return privateFunction();
};
})
模块模式
var singleton = function() {
//私有变量和函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//公有方法和属性
return {
publicProperty:true,
publicMethod:function() {
privateVariable++;
return privateFunction();
}
}
}();
增强的模块模式
var singleton = function() {
//私有变量和函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//创建对象
var object = new CustomType();
//添加公有方法和属性
object.publicProperty = true;
object.publicMethod = function() {
privateVariable++;
return privateFunction();
};
return object;
}();