JS
- ECMA2005
- BOM
- DOM
复制变量值
- 基础类型:会在新的变量上创建一个新值,存到新的变量列。两个变量互相不干扰、
- 引用类型:
ES函数参数
- es 函数传参的时候,并不在意参进来参数多少个。解析器不会去关注这个。 因为在函数内部,都是使用arguments这个类数组来取值的
function add(){
console.log(arguments.callee); // arguments.callee 为arguments所在的指针
}
var add2 = add; // 使用不带括号的函数名,访问的函数指针,跟复制引用类型值的一样的
- es 参数是按值传递的,也就是复制一份到函数的内部。这样的话,基本类型跟引用类型就有区别了
// 基本类型数据
function addTen(num){
num++;
return num
}
var count = 10
alert(addTen(count)); // 11
// 相对于函数内部执行了一层 num = count; 基本类型数据这两种是互相不影响的
alert(count); // 10
// 引用类型
function setName(obj){
obj.name = 'neibu';
obj = new Object();
obj.name = 'new neibu'
}
var person = new Object();
setName(person);
// 使用不带括号的函数名,访问的函数指针,跟复制引用类型值的一样的,所以js函数没有重载
function add(){
}
var add2 = add;
var a1 = function(){}
a1 = function(){};
// 后面一个a1 覆盖了前面一个a1的指针
//
函数内部属性
- arguments 类数组参数指针
function add(){
console.log(arguments.callee); // arguments.callee 为arguments所在的指针
}
- this:引用的是函数据以执行的环境对象
window.color = "red";
var o = {color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor(); // red
o.sayColor = sayColor;
o.sayColor(); // blue
// sayColor 是在全局定义的,引用this对象,调用函数之前,this的值不确定。因为this可能会在代码过程中引用不同的对象;
// ps 函数名字只是一个包含指针的变量。只是个变量
函数属性与方法
属性
- length 表示函数接收的参数个数
- prototype
方法
- call
- apply
ES 作用域
- 只能向上搜索,无法向下搜索变量
面向对象
创建对象
- 对象就是一个一系列无序的属性的集合
var obj = new Object()
var obj = {}
- 虽然Object构造函数和字面量可以创建对象,但是有个明显的缺点:会产生无序大量重复的代码,为了解决这个方法,使用工厂模式一种变体
- 6.2.1 工厂模式
function createPerson(name,age,jbo){
/*
* 工厂模式,内部创建个对象,往里面添加各种属性等。最后再返回
*/
var o = new Object();
o.name = name;
o.age = age;
o.sayName= function(){
return this.name
}
return o;
}
var ppp = createPerson();
- 6.2.2 构造函数模式 ,使用new 来调用,内部会自动添加上下文环境
function Person(name){
// var obj = new Object() 1 创建新对象(偷偷执行)
// 类似 obj.call(this) 2 将构造函数的作用域赋值给新对象
this.name = name; // 执行构造之间的代码(3)
this.sayName = function(){
}
// 偷偷执行return this
// 4 返回新对象
}
var ppp1 = new Person('name');
var ppp2 = new Person('name');
console.log(ppp1.sayName == ppp2.sayName);
- new 做了什么: // 1 创建新对象 2 将构造函数的作用域赋值给新对象,因此this就指向这个对象 3 执行构造之间的代码()添加新属性 4 返回新对象
// 衍生知识点 // constructor // 对象的constructor属性最初是来标识对象类型的,对象检测还可以使用方法 instanceof
// 构造函数缺点 // 构造函数里面的方法要在每个函数里面重新创建遍,影响内存,因为创建两个完全一样任务的方法实例没有必要的,改造如下
function PersonEdit(name){
this.name = name; // 执行构造之间的代码(3)
this.sayName = say;
}
function say(){}
- 6.2.3 原型模式
// 函数中prototype是个指针,指向一个原型对象。 作用是所有的实例都能共享到原型对象上方法跟属性
function Person(name){
}
console.log(Person.prototype,'6.2.3 原型模式')
Person.prototype.name = '原型上的name'
Person.prototype.sayName = function(){
}
var person1 = new Person();
console.log(Object.getPrototypeOf(person1)===Person.prototype); // 判断某个实例的原型
-
prototype 原型对象 一创建函数,就会为该函数创建prototype 的原型对象,默认有个constructor的属性,这个属性指向 函数本身的指针 上面例子 Person.prototype.constructor = Person
-
使用构造方式(new)调用函数,实例里有个 proto 指向原型对象,prototype; 实例对象就有原型对象上的方法跟属性
-
获取某个对象属性 // 每当代码获取对象某个属性,先搜索实例本身搜索,实例找到则返回,没有则继续搜索指针指向的原型对象 即实例__proto__
-
无法重写原型对象中的属性值,实例中如果定义了,则会先屏蔽下原型对象中的属性
使用delete删除实例属性,从而继续访问原型对象的属性
person1.name = "实例上的属性"
console.log(person1.name) // 实例上的属性
delete person1.name
console.log(person1.name) // 原型上的name
// in for-in 或者 in , 实例还是原型中的属性都能返回
for(var key in person1){
console.log(key)
}
// Object.keys 获取是实例上所有实例属性
var person2 = new Person();
person2.k = 3;
console.log(Object.keys(person2))
-
4 原型的动态性 由于原型中查找是一次搜索,所以对原型对象任何修改都能从实例中反映出来
var friend = new Person(); Person.prototype.sayFrind = function(){console.log('sayFrind')} friend.sayFrind(); // sayFriend // 首先创建 实例,在创建的时候调用sayFriend方法,又会找原型如果重新原型对象,就不同,如下
function Test (){};
var test = new Test(); // 先调用构造方法,此时test.__proto__ = Text.prototype; //等于它的原型对象,此时
Test.prototype ={ // 此时又重新了原型对象的指针
constructor:Test,
name:'test-name',
sayName:function(){
console.log(this.name)
}
}
console.log(test,'')
console.log(Object.isPrototypeOf(test) == Test.prototype)
test.sayName() // 所以这里报错
// 缺点 引用类型的数据会指向同一个指针 传参
- 6.2.4 组合使用构造函数与原型模式
function Person(name){
this.name = name;
}
Person.prototype.say = function(){}
- 6.2.5 动态原型模式。组合型封装型不够
function Person(name){
this.name = name;
if(typeof this.sayName!='function'){
Person.prototype.sayName = function(){}
}
}
- 6.2.6 寄生构造函数模式
继承
OO(面向对象都支持两种继承方式)
- 接口继承
接口继承制继承方法签名,即只继承属性名称,里面的功能不管, - 实现继承
实现继承则把实际的方法功能。
js 无接口继承,只有方法继承,而且都是通过基本使用的原型链来的
- 6.3.1 原型链继承
(这里得知道ecma中原型对象的概念)函数的原型对象等于另外一个函数的实例,那这个函数的实例不就有另外一个函数所有属性跟方法了么。例子
function SuperType(){
this.property = '父类属性';
}
SuperType.prototype.getSuperValue = function(){
return this.property
}
function SubType(){
this.subproperty = '子类属性'
}
// 继承了父类SuperType
SubType.prototype = new SuperType(); // 没有使用subType提供的默认原型,而是重写了原型对象,这也是实现本质
var instance = new SubType();
console.log(instance,'instance')
- 确定原型与实例的关系
- instanceof 原理:用instanceof
console.log(instance instanceof SubType); // true
console.log(instance instanceof SuperType);// true
console.log(instance instanceof Object); // ture
由于 instance 是 SubType、SuperType、Object 中任何一种类型的实例,所以都返回 true
- isPrototyoeOf()
Object.prototype.isPrototypeOf(instance);// true
SuperType.prototype.isPrototypeOf(instance);// true
SubType.prototype.isPrototypeOf(instance);// true