对象
对象的创建方法
-
var obj = {} ----plainObject 对象字面量/对象直接量
-
构造函数
- 系统自带的构造函数 new Object() /Array() /Number()
var obj = new Object();
- 自定义
function Student(name){
this.name = name;
this.grade = 2016;
this.read = function(){...}
}
var studentHo = new Student('HoYuu');
构造函数内部原理
- 在函数体最前面隐式加上this = {}
- 执行 this.xxx = xxx;
- 隐式地返回this
包装类
String()
Number()
Boolean()
原型 prototype
prototype -----是祖先,值是一个对象
自身就有,初始为空对象,可手动添加属性
构造函数上的一个属性
eg.
Student.prototype.school = 'tust';
function Student(name){
this.name = name;
this.grade = 2016;
this.read = function(){...}
}
var studentHo = new Student('HoYuu');
studentHo.school;
constructor
构造函数,原型中自带的属性之一
原型 proto
对象身上的
自带属性之一,也是原型(prototype是标准的,__proto__是非标准的——浏览器自己部署的)
eg.
Student 中
this = {
__proto__:Student.prototype
}
Student.prototype 中
__proto__:object
- 对象找构造函数:obj.constructor
- 对象找原型:obj.prototype
浏览器添加了一条属性,代表构造函数上的原型:__ proto __
__ proto __ === constructor.prototype
对象.__ proto__ === 其构造函数.constructor.prototype
原型链
Object.creat(原型)
绝大多数对象的最终都会继承自Object.prototype
例外:Object.creat(null);
bug
JS 精度略微不准:
可正常计算的范围:小数点前16位,后16位
输出随机数
for(var i = 0; i < 10; i++){
// toFix(n) , 保留n位小数
// 向上取整ceil , 向下取整floor
var num = Math.floor(Math.random()*100);
console.log(num);
}
call/apply
作用:改变this指向
区别:后面传的参数形式不同
function Person(name,age){
this.name = name;
this.age = age;
}
var obj = {}
Person.call(obj,'小明',20);
// this ----> obj
obj.name;// 小明
obj.age;// 20
function Person(name,sex,age)
{
this.name = name;
this.sex = sex;
this.age = age;
}
function Student(name,sex,age,tel,grade){
Person.call(this,name,sex,age);
// Person.apply(this,[name,sex,age]);
this.tel = tel;
this.grade = grade;
}
var student = new Student('大富','男',18,13536,2018);
继承发展史
-
传统形式 ------原型链
缺点:继承了过多没用的属性 -
借用构造函数 -------call/apply
不能继承借用构造函数的原型
每次构造函数都要多走一个函数 -
共享原型
Son.prototype = Father.prototype;
不能随便改动自己的原型
Son往原型上添加信息,Father的原型也会有同样改变
- 圣杯模式
function F(){}
F.prototype = Father.protoytpe;
Son.prototype = new F();
封装成函数
function inherit(Target,Origin){
function F(){};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;//可不写,知道真正继承自谁
}
inherit(Son,Father);
var son = new Son();
更好的写法:
var inherit = (function (){
function F(){};
return function(Target,Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
命名空间
管理变量,防止污染全局,适用于模块化开发
更简洁:使用闭包-----立即执行函数,返回函数
属性的表示方法
- object.prop
- object[‘prop’]
对象的枚举
for in
会把原型的属性也打印出来
var obj = {
name : 'zfx',
age : 18,
grade : 'perfect',
face : 100
}
// 打印出对象的属性
for(var prop in obj){
console.log(prop);
// 或者 console.log(obj[prop]);
// 不能写成: obj.prop
}
- !!! hasOwnProperty
判断属性是否是自身拥有而不是原型的
if(obj.hasOwnProperty()){
console.log(obj[prop]);
}
-
in
-
!!! instanceof
A instanceof B
实际:看A对象的原型链上,是否有B的原型
有一个变量,可能是 数组 或 对象,判断是哪种
var arr = [] || {};
-
arr.constructor();
数组返回 Array()
对象返回 Object() -
arr instanceof Array
数组返回 true
对象返回 false -
Object.propeotype.toString.call(arr);
数组返回 [Object Array]
对象返回 [Object Object]
this
- 函数预编译过程 this ----》window
- 全局作用域里 this ----》window
- call/apply 可以改变函数运行时this指向
- obj.func(); func()里的 this 指向 obj
var name = '222';
var a = {
name : '111',
say : function (){
console.log(this.name);
}
}
var fun = a.say;
fun(); //222
a.say(); //111
var b = {
name : '333',
say : function (fun){
fun();
}
}
b.say(a.say); //222
b.say = a.say;
b.say(); //333
arguments
- arguments.callee() 函数自身的引用
// 计算n的阶乘
var num = (function(n){
if(n == 1){
return 1;
}else return n * arguments.callee(n-1);
}(10))
- func.caller 函数是在哪被调用的
function demo(){
test();
}
function test(){
console.log(test.caller);
}
demo();
// 控制台结果:demo...
克隆
var obj = {
name : 'loly',
height : 80,
card : ['hello','vivi']
}
var obj1 = {};
function clone (Origin, Target){
Target = Target || {};//当没有传第二个参数时,自创Target为空对象
for(var prop in Origin){
Target[prop] = Origin[prop];
}
}
clone(boj, obj1);
// obj1 其他属性值改变, obj 对应的不会改变;
// 但obj1 改变 card(数组)的值, obj 对应的也会改变
深度克隆
要求 obj1 无论改变什么值,都不会影响 obj
function deepClone(origin, target) {
target = target || {};
var prop,
arrStr = Object.prototype.toString,
toStr = '[object Array]';
for (prop in origin) {
if (origin.hasOwnProperty(prop)) {
// 只克隆对象自身拥有的属性,而不克隆其原型链上的
if (prop !== null && typeof (origin[prop]) == 'object') {
//当属性值不为null 且 属性值为引用值
if (arrStr.call(prop) == 'toStr') {
//当引用值为数组
target[prop] = [];
} else {
// 当引用值为对象
target[prop] = {};
}
// 递归
deepClone(origin[prop], target[prop]);
} else {
//当属性值为原始值
target[prop] = origin[prop];
}
}
}
return target;
}
deepClone(obj, obj1);
三目运算符
?:
条件判断? 是 :否 且返回值
var num = 1 > 0 ? 6+5 : 1-5;
不可配置属性
有var的属性,是不可配置属性,不能delete
var num = 1223;
delete window.num; ----false