对 象
对象的 增 删 改 查
var deng = {
perparewife: "xiaownag",
neme: "laodeng",
age: 40,
sex: "male",
gf: "xiaoliu",
wife: "",
health:100,
divorce: function(){
delete this.wife; 删 除
this.gf = this.perparewife;
},
getMarride: function(){
this.wife = this.gf;
},
chagePerparWife: function(someone){
this.PerparWife = someone;
}
}
对 象 的 创建方法:
-
var obj = { } plainObject 对象字面量 / 对象直接量
-
构造函数:
(构造函数 和 一般函数的定义方式极其相似,为了区别它们,构造函数的命名要符合大驼峰式命名规则)
例如:
The First Name 为 大驼峰式命名
the First Name 为 小骆驼峰式命名
1)系统自带的构造函数 new Object()
2) 自定义 -
Object.create(原型):
例如:
Person.prototype.name = “sunny”;
function Person() { }
var person = Object.cerate(Person.prototype);构 造 函 数 内部原理 三 段 论 :
1.在函数体最前面隐式的加上 this = { proto : Object.prototype—原型变量终端}
初始为一个空对象,实际存放在原型
2.执行 this.xxx = xxx;
3.隐式的返回 this{ } 对象function Car (color) { //隐式生成 var this = { } 的一个空对象 this.color = color; this.name = "BMW"; this.height = "1400"; this.lang = "4900"; this.weight = 1000; this.health = 100; this.run = function () { this.health --; } //隐式的 return this; } var car = new Car( 'red'); var car1 = new Car('greed');
包 装 类
new String();
new Boolean(); ----- 包装类
new Number();
String Boolean Number ----- 称为原始值,原始值没有 属性 和 方法
例题:
var str = "abc";
str += 1;
var test = typeof(str);
tset = "String" ;
if(test.length == 6){
new String(test).lenght = 6 //隐式
test.sign = " typeof的返回结果可能为String ";
new String(test).sign = "typeof的返回结果可能为String" 隐式
// delete 隐式
}
new String(test).sign
console.log(test.sign);
包装类的一个整体过程:
var num = 123;
num 现在是原始值,而正常原始值是没有属性的,
现在给 num 强行添加一个 abc 的属性,系统仍然不会报错
因为内部进行了 包装类 的操作:
首先判断出 num 的类型为 Number
然后再进行 new Number(num).abc = ‘abc’ ----> delete
生成了Number对象并赋值之后,该对象就会立刻被撤销 num.abc = ‘abc’;
再次访问 num.abc ----> 再重新 new Number(num).abc
此时 num.abc 是没有值的,于是会返回一个 undefined
console.log(num.abc);
啊 里 巴 巴 笔 试 题: 下列arguments 的输出结果为 12345 的是 A C D
A
function food(x){
console.log(arguments);
return x;}
food(1,2,3,4,5);
B
function food(x){
console.log(arguments);
eturn x; } (1,2,3,4,5)
// 不报错,也不执行
C
(function food(x){
console.log(arguments)
return x; }) (1,2,3,4,5)
D
function foo() {
bar.apply(null,arguments)
}
function bar(x) {
console.log(arguments)
}
foo(1,2,3,4,5)
原 型 ( prototype ) —————————— 也是对象
原 型 必须是基于 构造函数 的,没有构造函数,原型就没有意义
而任何一个函数都会有一个 prototype 属性,它是这个函数构造出 对象 的公有祖先
1. 定义:原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先; 通过该结构函数产生的对象,可以继承原型的属性和方法.
2. 利用原型的特点和概念,可以提取公共属性.
3. 对象如何查看原型 ——-> 隐式属性 **_proto _ ** 里面存放的是 原 型(prototype)
4. 对象如何查看对象的构造函数 ——————> constructor .
Car.construtor 查看原型
5. 绝大多数对象的最终 都会继承自 Object.prototype
( 不是所有都是继承自 Object.prototype,存在 **Object.create( null )**的特例 ) Object.create( 此处就只能放 对象 或 Null )
Person.prototype ————————> 原型,是 Person 的祖先
Person.prototype = { } ————————> 可以理解为一个空对象
Person.prototype = { name : “hehe” } 两种写的方式 :
1. Person.prototype.name = “hehe”;
2. function Person(){ }
var person = new Person();
person.name = ’ hehe ’
c a l l / a p p l y ———————————— 小知识,广应用
作用: 改变 this 的指向
区别: 后面 传的 参数形式不同
1. call 需要把实参按照形参的个数传进去
2. apply 需要传一个 arguments
.
call 的作用 例如:
1. 当 .call() 中没有任何参数 function test(){ } ————————> 函数声明
test(); ——————————————> 函数执行 ————————> 实际内部操作为:
test.call();
2. 当 .call() 中传进一个对象参数 ,根本作用还是改变 this 的指向
( 借用别人的函数是实现自己的功能 )
例如:实现 person 对象的 this 会指向 obj 对象
function Person(name,age){
this.name = name;
this.age = age;
}
var person = new Person('deng',100);
var obj = { }
Person.call(obj,'cheng',300);
apply 的用法:
例如:
function Person(name,age){
this.name = name;
this.age = age;
}
var person = new Person('deng',100);
var obj = { }
Person.apply(obj, ['cheng',300] );
继 承 发 展 史
1. 传统形式 ————> 原型链 (过多的继承了没用的 属性)
2. 借用构造函数 ——— ( 不能继承借用构造函数的原型 ;每次构造函数都要夺走一个函数 )
(“ 工业开发上还是建议用此方法 ”,只是说继承的角度来说第三种更好)
3. 共享原型 ———— (不能随便改动自己的原型)
4. 圣杯模式
原 型 链 式 继 承
Father.prototype.lastName = "Deng";
function Father (){}
var father = new Father();
Son.prototype = father;
function Son (){ }
var son = new Son();
call( ) 调用 (准确的说 不算是 继承)
function Person (age, name, sex){
this.age = age;
this.name = name;
this.sex = sex;
}
function Student (age,name,sex,grade){
Person.call(this,age,name,sex,grade);
this.grade = grade;
}
var student = new Student(23,"dneg","male",2018);
共享原型 模式 (实现了 A 继承 B)
// 继承之后,有一个改动,另一个也会改动,无法实现真正的个性化
Father.prototype.lastName = "deng";
function Father (){ }
function Son (){ }
Son.prototype = Father.prototype ; // 将此功能封装到函数 inherit 里(重要技能学习)
function inherit(target, origin){
target.prototype = origin.prototype;
}
// 必须 先继承 后使用,意味着必须在 new 之前完成继承 inherit(Son, Father);
var son = new Son();
var father = new Father();
圣杯模式 (继承 的丰满模式)
Father.prototype.lastName = "deng";
function Father (){ }
// 此处也封装到 inherit 函数中
function F (){ }
F.prototype = Father.prototype;
Son.prototype = new F();
// 由于继承之后,Son 的 constuctor 指向会紊乱,
// 这一步是规正 Son 的 constuctor
Son.prototype.constuctor = Son;
// 这一步是方便日后若是想知道,Son 真正继承于谁
Son.prototype.uber = Father.prototype;
function Son (){ }
// 圣杯模式 函数封装
function inherit(target, origin){
function F () { };
F.prototype = origin.prototype;
target.prototype = new F();
// 由于继承之后,Son 的 constuctor 指向会紊乱,
// 这一步是规正 Son 的 constuctor
target.prototype.constuctor = target;
// 这一步是方便日后若是想知道,Son 真正继承于谁
target.prototype.uber = origin.prototype;
}
// 必须先继承后使用,意味着必须在 new 之前完成继承 inherit(Son, Father);
var son = new Son();
var father = new Father();
// inherit 更 高 级 的 写 法
var inherit = ( function (){
// 闭包的私有化功能
var F = function () { };
F.prototype = origin.prototype;
target.prototype = new F();
target.prototype.constuctor = target;
target.prototype.uber = origin.prototype;
});