对象

用已学的知识点,描述一下你心目中的对象

var mrDeng = {      name : "mrDeng",age : 40,sex : "male",health : 100,//可在控制台更改smoke : function () {console.log('I am smoking');mrDeng.health --;},drink : function () {console.log('I am drink');mrDeng.health ++;}
}

改进 第一人称:this

var mrDeng = {      name : "mrDeng",   千万别是等于号age : 40,sex : "male",health : 100,//可在控制台更改smoke : function () {console.log('I am smoking');this.health --;},drink : function () {console.log('I am drink');this.health ++;}
}

1.属性的增、删、改、查

drink:function(){console.log('I am drinking');this.health ++;
}
meDeng.wife = "xiaowang";
// console.log(mrDeng.wife = "xiaoliu");
// console.log(mrDeng);

console.log(mrDeng);
console.log(mrDeng.sex = "male");
console.log(mrDeng.sex);

删 delete + 属性

当一个变量没有声明就是用报错,对象的属性没有就访问打印undefined,不会报错

var deng = {prepareWife : "xiaowang",name : "laodeng",sex : "male",gf : "xiaoliu",wife : "",divorce : function () {delete this.wife;this.gf = this.PrepareWife;},getMarried : function () {this.wife = this.gf;},changePrepareWife : function (someone){this.PrepareWife = someone;}
}

2.对象的创建方法

1.var obj = {} 叫plainObject 对象字面量/对象直接量

2.构造函数

(1) 系统自带的构造函数 new Object

var obj = new Object();
obj.name = 'abc';
obj.sex = 'female';
obj.say = function(){
}
var obj = {name : ""
}

系统提供的:new Object();Array();Number();Boolean();Date();

(2) 自定义

function Car(){//方便使用-人为的,构造函数特点:大驼峰式命名规则,只要是单词,首字母大写(小驼峰式:第一个外的首字母大写)this.name = "BMW";this.height = "1400";this.lang = "4900";this.weight = 1000;this.health = 100;this.run = function (){this.health --;}
}
var car = new Car();//每个都一样,但是每个都独立
var car1 = new Car();//不是一个人,不互通
console.log(car.run());
console.log(car1.health);
console.log(car.health);

demo

实现自己选配颜色

function Car(color){this.color = color;this.name = "BMW";this.height = "1400";this.lang = "4900";this.weight = 1000;this.health = 100;this.run = function (){this.health --;}
}
var car = new Car('red');
var car1 = new Car('green');
console.log(car/car1);
function Student(name,age,sex) {    this.name = name;    this.age = age;    this.sex = sex;    this.grade = 2017;}var student = new Student('zhangsan',18,'male');

注意事项

var obj = new Object(){    obj.name = 'abc';    obj.sex = 'female';    obj.say = function(){    }}
var obj = {    name : ""//冒号}

构造函数内部原理

有new 则发生三步

1.在函数体最前面隐式的加上var this = {}
2.执行 this.xxx = xxx;
3.隐式的返回this

function Student(name,age,sex) {    //var this = {    // name : ""    // age :     // };    this.name = name;    this.age = age;    this.sex = sex;    this.grade = 2017;    // return this;}var student = new Student('zhangsan',18,'male');
function Person(name, height){    // var this = {}    this.name = name;    this.height = height;    this.say = function (){        console.log(this.say);    }    // return this;}console.log(new Person('xiaoliu',180).name);

模拟构造函数

function Person(name, height){    var that = {};    that.name = name;    that.height = height;    return that;}var person = new Person('xiaowang', 180);var person1 = new Person('xiaozhang',175);

冷门知识

function Person(name, height){    var this = {};    this.name = name;    this.height = height;    this.say = function    (){        console.log(this.say);    }    return {};//显示返回空对象,so person很person1都返回空对象    // return this;}var person = new Person('xiaowang', 180);var person1 = new Person('xiaozhang',175);// 但是return一个原始值不允许

Object.create(原型)方法

包装类

1.小知识

原始值不能有属性和方法,只有对象能有,对象包括对象自己,数组,function。
数字不一定是原始值。数字分两种:原始值数字才是原始值。数字,字符串分为两种。
var num = 123;数字
Var num = new number(123);也数字,对象123

console.log(num);console.log(num.abc='a');console.log(num.abc);console.log(num);console.log(num*2);//成了数字,没有了对象属性,同理字符串,布尔

不能有属性的两个原始值:undefined null

String();
Boolean();
Number();

var num = new Number(123);var str = new String('abcd');var bol = new Boolean('true');// undefined与null不可以有属性console.log(num.abc);

2.现象:

var str = “abcd”;str.length = 4;//理论上不可以str.abc = ‘a’;str.abc = undefined;

原始值不可能有属性和方法,因为经历了一个过程——包装类,才能调用

var num = 4;//包装类console.log(num.len = 3);//new Number(4).len = 3;  delete// new Number(4).lenconsole.len(num.len);//undefined// num没有length

考题

基于一个理论:数组截断

var arr = [a,b,c,d];console.log(arr.length = 2);console.log(arr);

成哥真题

var str = "abcd";str.length = 2;// new String('abcd').length = 2;deleteconsole.log(str);//abcd

变式

var str = "abcd";str.length = 2;// new String('abcd').length = 2;delete// new String('abcd').lengthconsole.log(str.length);//4

原形

1.定义

原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。

构造函数产生的对象:

// Person.prototype = {} 是祖先    Person.prototype.name = "hehe";function Person() {}var person = new Person();

应用:

实例一:自己有取自己的

Person.prototype.LastName = "Deng";Person.prototype.say  = function(){    console.log('hehe');}function Person() {    // this.LastName = 'ji';先看自己后看父亲}var person = new Person();var person1 = new Person();

实例二:

Person.prototype.LastName = "Deng";Person.prototype.say  = function(){    console.log('hehe');}function Person(name,age,sex) {    this.name = name;    this.age = age;    this.sex = sex;}var person = new Person('xuming',30,'male');

2.提取共有属性。

function Car(color,owner) {    this.owner = owner;    this.carName = "BMW";//每次生产都得执行这三句,耦合    this.height = 1400;    this.lang = 8900;    this.color = color;}var car = new Car('red','prof.ji');

优化

Car.prototype.height = 1400;Car.prototype.lang = 8900;Car.prototype.carName = "BMW";function Car(color,owner) {    this.owner = owner;    this.color = color;}var car = new Car('red','prof.ji');var car1 = new Car('green','laodeng');

3.原形的增删改查

Person.prototype.lastName = "Deng";//原形属性没有改,想改,就要调用Person.prototyoe.lastNamefunction Person(name) {    this.name = name;}var person = new Person('xuming');
console.log(person.lastName="james");//这不叫修改,这叫增加console.log(person);console.log(person.lastName);

console.log(delete person.name);console.log(person.name);console.log(delete person.lastName);console.log(person.lastName);//删除失效

优化

Car.prototype.height = 1400;Car.prototype.lang = 8900;Car.prototype.carName = "BMW";一步到位Car.prototype = {    height : 1400,    lang : 4900,    carName : "BMW"}

2.对象如何查看对象的构造函数 — > constructor构造器

function Person(){}//可以手动更改//构造器constructor:谁生的Car.prototype = {    constructor : Person}function Car(){}var car = new Car();console.log(car.constructor);

  1. 对象如何查看原型 — > 隐式属性 proto
function Person(){}var person = new Person();//浅紫色,隐式命名规则console.log(person);
person.prototype.name = 'abc';function Person(){}var person = new Person();// 私人属性:var __praviteconsole.log(person.__proto__)//__proto__里面放的是原形
Person.prototype.name = 'abc';function Person(){    var this = {        // __proto__: Person.prototype    }}//先看看自己有没有name属性,没有的话沿着proto指向找var perosn = new Person();console.log(perosn.name);

改变proto指向会使得指向更改

Person.prototype.name = 'abc';function Person() {    // var this = {    //   // __proto__: Person.prototype    // }}var obj = {    name: "sunny"}var person = new Person();//换爹person.__proto__ = obj;

演示1

Person.prototype.name = "sunny";function Person() {}var person = new Person();Person.prototype.name = "cherry";person.name; 分析:自己没有,找proto,是Person.prototype:sunny,最后又改成cherry

演示2

Person.prototype.name = "sunny";function Person() {}Person.prototype.name = "cherry";var person = new Person();console.log(person.name); 同理分析cherry

演示3

Person.prototype.name = "sunny";function Person() {}var person = new Person();Person.prototype = {    name : "cherry"}person.name; 答案:sunny。        .的写法是原有的基础上把原有的值改了,这一次是把原形改了,换了个新对象

简化:引用值的互相赋值

var obj = {name : "a"};var obj1 = obj;obj = {name : "b"};obj1:a,obj:b
Person.Prototype.name = "sunny";function Person() {    //var this = {__proto__:Person.prototype}}//proto指向不变还是sunnyvar person  = new Person();Person.prototype = {//把自己空间换了    name:'cherry'}// 更加简化// Perosn.prototype = {name:"a"};// __proto__ = Person.Prototype;// Person.Prototype = {name:"b"};

演示4

Person.prototype.name = "sunny";function Person() {}Person.prototype = {    name: "cherry"}var person = new Person();person.name;答案:cherry预编译:函数 function Person() { } 提升到最上面,然后顺序执行,执行到最后一行,有new了,就有function Person() { var this = __proto__ Person.prototype } ,再访问:下面的把上覆盖

原型链引入

Grand.prototype.LastName = "Deng";function Gand(){}var grand = new Grand();Father.prototype = grand;function Father(){    this.name  = "xuming";}var father = new Father();Son.prototype = father;function Son(){    this.hobbit = "somke";}var son = new Son();console.log(son.hobbit);console.log(son.name);//顺着链找console.log(son.toString);Grand.prototype.__proto__=Object.prototype是所有对象的最终原形console.log(Object.prototype);console.log(Object.prototype.__proto__);proto没了,so就是终端

原型链

如何构成原型链?

1.原型链上属性的增删改查

增,删,修改:只有本人有权限,子孙没有

console.log(delete Father.prototype.n);//删不了

特例:引用值调用修改

var grand = new Grand();Father.prototype = grand;function Father() {    this.name = 'xuming';    this.fortune = {        card1 : 'visa'    }}var father = new Father();Son.prototype = father;function Son(){    this.hobbit = "somoke";}var son =  new Son();
console.log(son.fortune);son.fortune = 200;console.log(son);console.log(father.fortune);son.fortune.card2 = 'master';cons.log(father);

demo

Grand.prototype.LastName = "Deng";function Grand(){}var grand = new Grand();Father.prototype = grand;function Father(){    this.name = "xuming";    this.forture = {        card1 : 'visa'    };    this.num = 100;}var father = new Father();Son.prototype = father;function Son(){    this.hobbit = "smoke";}var son = new Son();
console.log(son.num++);100console.log(father);100console.log(son.num);101

演示

Person.prototype = {    name : "a",    sayName : function(){        console.log(this.name);    }}function Person(){}var person = new Person();//答案:a
Person.prototype = {    name : "a",    sayName : function(){        console.log(this.name);    }}function Person(){    this.name = "b";}var person = new Person();

小常识:
a.sayName()
sayName里面的this指向是,谁调用的这个方法,this就指向谁
person.sayName(); person调用的,b
如果Person.prototype.sayName(); a

Person.prototype = {    height : 100}function Person(){    this.eat = function(){        this.height ++;    }}var person = new Person();
console.log(person.eat);person.eat();console.log(person.eat);//默認return:undefined 查看要写代码

公司规范:数组,对象都用字面量创建

var obj = {};//对象自变量创建形式,有原形//与var obj1 = new Object();相同var obj = {};内部来一个new Object()所以要写对象字面量

绝大多数对象的最终都会继承自Object.prototype

(选择题真题)
例外:由于Object.create

console.log(Object.create());//报错,不写代码console.log(Object.create(null));

Object.create(原型)也能创造对象

// var obj = Object(原形);var obj = {name : "sunny", age : 123};var obj1 = Object.create(obj);// obj1成为了对象,obj1的原形是obj,所以obj1.name就是obj.name
Person.prototype.name = "sunny";function Person() {}var person = Object.create(Person.prototype);

2.关于toString:

只有undefined与null不能调用toString
数字可以,因为经过包装类一层层访问123.toString();
undefined没有包装类,是个原始值,没有原形,不能调用

console.log(undefined.toString);console.log(null.toString);obj.__proto__ = { name: sunny};console.log(obj.name);//自己加原形不管用

各个变量各个属性值调用toString返回结果不一样 变成字符串

var num = 123;console.log(num.toString);//字符串console.log(123.toString);//识别成浮点型

现象

var obj = {};obj.toString();---->[object Object]

原因

var num = 123;// num.toString();-->new Number(num).toString();Number.prototype.toString = function (){}// Number.prototype.__proto__ = Object.prototype

重写笔试题:写一个方法重写形式,写一个和系统同样的名,不同功能

// Object.prototype.toString = function (){// } Person.prototype = {    toString : function () {        return 'hehhe';    }}function Person () {}var Person = new Person();

本集多看弱项

3.小bug

console.log(0.4*100);//js精度不准console.log(Math.ceil(123.234));//向上取整console.log(Math.floor(123.99999));//下

随机生成0-100随机数

Math.random();//随机数生成函数(0,1)for(var i = 0;i < 10; i++){    var num  = Math.random().toFixed(2)*100;    console.log(num);//会出现偏差}

解决:先*100后取整

for(var i = 0; i < 10; i++){    var num = Math.floor(Math.random() * 100);    console.log(num);}// 总结:可正常那个计算的范围:小数点前16后16

call/apply 必考

1.call

作用,改变this指向。借用别人的函数实现自己的功能
区别,后面传的参数形式不同。
call需要把实参按照形参的个数传出去 apply需要传一个arguments

function test(){}test()===test.call();//后面隐式默认

call里面可以传东西

function Person(name, age){    this.name = name;    this.age = age}var person = new Person('deng',100);var obj = {}// Person.call(obj);// 会让Person里所有的this变成obj 即this=obj// 怎么传参:Person.call(obj,'cheng',300);Person.call(obj,'cheng',300);

企业级开发

//开发讲究快准狠,A写的代码能实现B的功能,省时function Person(name, age, sex) {    this.name = name;    this.age = age;    this.sex = sex;}function Student(name, age, sex, tel, grade){    this.name = name;    this.age = age;    this.sex = sex;    this.tel = tel;    this.grade = grade;//后面覆盖前面}// call 借用别人的函数实线自己的功能function Person(name, age, sex) {    this.name = name;    this.age = age;    this.sex = sex;}function Student(name, age, sex, tel, grade){    // var this = {name : "", age : "",sex : ""}    Person.call(this, name, age, sex);    this.tel = tel;    this.grade = grade;}var student = new Student('sunny',123,'male',139,2017);

造车举例

function Wheel(wheelSize,style) {    this.style = style;    this.wheelSize = wheelSize;}function Sit(c,sitColor) {    this.c = c;    this.sitColor = sitColor;}function Model(height,width,len) {    this.height = height;    this.width = width;    this.len = len;}function Car(wheelSize, style, c, sitColor, height, width, len) {    Wheel.call(this, wheelSize,style);    Sit.call(this,c,sitColor);    Model.call(this, height, width, len);}var car = new Car(100,'花里胡哨的','真皮','red',1800,1900,4900);

2.apply:

apply只能传送一个数组形式的实参
Wheel.apply(this, [wheelSize,style]);

总结:

call:需要把实参按照形参的个数传进去

apply: 需要传一个arguments

作业:电子书js设计模式0-35页上部分

笔试题:用友2017校招前端

继承发展史

1.传统形式

过多的继承了没用的属性

Grand.prototype.lastName = "Ji";function Grand() {}var grand = new Grand();Father.prototype = grand;function Father() {    this.name = "hehe";}var father = new Father();Son.prototype = father;function Son() {}var son = new Son();//一系列从头到尾继承,导致不想继续的也继承了

2.借用构造函数

不能继承借用构造函数的原型
每次构造函数都要多走一个函数实际浪费效率

function Person(name,age,sex){    this.name = name;    this.age = age;    this.sex = sex;}//实际上call apply不是继承function Student(name, age, sex, grade) {    Person.call(this,name,age,sex);    this.grade = grade;}var student = new Student();

3.共享原型

不能随便改动自己的原型

Father.prototype.lastName = "Deng";function Father(){    // Son想继承father的prototype}function Son(){}

实现方法

  1. 原型链

    function Son()上面放上var father…

  2. 共有原形

Father.prototype.lastName = "Deng";function Father() {}function Son() {}Son.prototype = Father.prototypevar son = new Son();var father = new Father();

抽象成函数

Father.prototype.lastName = "Deng";function Father() {}function Son() {}function inherit(Target, Origin) {    Target.prototype = Origin.prototype;}inherit(Son, Father);var son = new Son();//son.LastName = "Deng";

要先继承后使用,Son.lastName指向原来的空间

Father.prototype.lastName = "Deng";function Father() {}function Son() {}function inherit(Target, Origin) {    Target.prototype = Origin.prototype;}var son = new Son();inherit(Son, Father);    //先继承,后该原形不管用 son.lastName = undefined

不足:

son给自己多加一个属性,方便后续生产出的对象使用,不能个性实现,继承了,但是影响

Father.prototype.lastName = "Deng";function Father(){}function Son(){}function inherit(Target, Origin){    Target.prototype = Origin.prototype;}inherit(Son, Father);Son.prototype.sex = "male";//与father的prototype一致,一个变,都变Father.prototypevar son = new Son();var father = new Father();// 要实现:想继承但不相互影响

4.圣杯模式

通过原型链

function inherit(Target, Origin) {    function F(){};    F.prototype = Origin.prototype;    Target.prototype = new F();}Father.prototype.lastName = "Deng";function Father(){}function Son() {}inherit(Son,Father);var son = new Son;var father = new Father();console.log(Son.prototype.sex = "male");console.log(son.sex);console.log(father.sex);console.log(Father.prototype);

但是,constructor应该指向构造函数,然而,son.constructor = ƒ Father()????怎么回事?

原形上系统自带的一个属性叫constructor,默认指向他的构造函数

son.__proto__ --->new F().__proto__--->Father.prototype//指向紊乱了

实现继承:必会圣杯模式

function inherit(Target, Origin){    function F(){};    F.prototype = Origin.prototype;    Target.prototype = new F();    Target.prototype.constructor = Target;    Target.prototype.uber = Origin.prototype;//超级父级:超类}Father.prototype.lastName = "Deng";function Father(){}function Son(){}inherit(Son, Father);var son = new Son();var father = new Father();

颠倒

F.prototype = Origin.prototype;Target.prototype = new F();//不能颠倒,一定要在new之前改原形

类雅虎

闭包的作用:可以实现封装,属性私有化

function Deng(name, wife){    var prepareWife = "xiaozhang";    this.name = name;    this.wife = wife;    this.divorce = function(){        this.wife = prepareWife;    }    this.changePrepareWife = function(target){        prepareWife = target;    }    this.sayPreparewife = function(){        console.log(prepareWife);    }}var deng = new Deng('deng','xiaoliu');
console.log(deng.sayPreparewife());console.log(deng.Preparewife)//直接看看不到  即私有化变量

F变成了私有化变量

var inherit = (function(){    var F = function(){};//F放在闭包,私有化变量    return function(Target,Origin){        F.prototype = Origin.prototype;        Target.prototype = new F();        Target.prototype.constuctor = Target;        Target.prototype.uber = Origin.prototype;    }}());

离散数学(重要)——>CS专业(计算机专业),,,,概率论,人工智能

命名空间

就是对象

管理变量,防止污染全局,适用于模块化开发

一个页面,多人协作,合并冲突

1.老办法:命名空间

var org = {    department1 : {        jicheng : {            name : "abc";            age : 123;        },        xuming : {        }    },    department2 : {        zhangsan : {        },        lisi : {        }    }}var jicheng = org.department1.jicheng;jicheng.name;

2.新方法:闭包私有化变量

webpack

闭包(实现变量私有化)+立即执行函数

var name = "bac";var init = (function(){    var name = "abc";    function callName(){        console.log(name);    }    return function(){        callName();    }}())init();

协作也不冲突

var name = "bac";var init = (function(){    var name = "abc";    function callName(){        console.log(name);    }    return function(){        callName();    }}())var initDeng = (function(){    var name = 123;    function callName(){        console.log(name);    }    return function(){        callName();    }}())

如何实现链式调用模式(模仿jquery)
obj.eat().smoke().drink().eat().sleep();

$('div').css('background-color','red').width(100).height(100).html(123).css('position','absolute').css('left','100px').css('top','100px');

模拟jQuery实现连续调用方法

var deng = {    smoke : function () {        console.log('Smoking...xuan cool!!!');    },    drink : function () {        console.log('Drinking...good');    },    perm : function(){        console.log('perming...cool');    }}deng.smoke();deng.drink();deng.perm();//怎么实现JQ一样连续调用

为什么不能连续调用

console.log('Smoking...xuan cool!!!');// return undefined;

方法:

var deng = {    smoke : function () {        console.log('Smoking...xuan cool!!!');        return this;    },    drink : function () {        console.log('Drinking...good');        return this;    },    perm : function(){        console.log('perming...cool');        return this;    }}deng.smoke().drink().perm().smoke().drink();

查看属性

想实现num为几,就叫哪个媳妇

var deng = {    wife1 : {name : "xiaoliu"},    wife2 : {name : "xiaozhang"},    wife3 : {name : "xiaowang"},    wife4 : {name : "xiaoli"},    sayWife : function(num) {        switch(num) {            case 1:                return this.wife1;        }    }}

把上述代码简化:变量拼接属性名

var obj = {    name : "abc"}

**obj.name---->obj[‘name’];**内部会转换成方括号,so这样写也对
方括号可以字符串拼接
功能实现

var deng = {    wife1 : {name : "xiaoliu"},    wife2 : {name : "xiaozhang"},    wife3 : {name : "xiaowang"},    wife4 : {name : "xiaoli"},    sayWife : function(num) {        switch(num) {            case 1:                return this['wife' + num];//字符串加啥都是字符串        }    }}console.log(deng.sayWife(1));

对象的枚举

for in 循环

数据组的遍历:想知道十个人的信息,挨个知道

var arr = [1,3,3,4,5,6,7,8,9];//遍历 枚举 enumerationfor(var i = 0; i < arr.length; i++){    console.log(arr[i]);//遍历}

如果想查找(遍历)对象的呢(不知道啥类型,编辑器角度)

var obj = {    name : "123",    age : 123,    sex : "male",    height : 180,    weight : 75    //prop:123}for(var prop in obj){    console.log(obj.prop);//不好使---obj.prop--->obj['prop']当成属性了}

正解:

var obj = {    name : '13',    age : 123,    sex : "male",    height : 180,    weight : 178,    __proto__ : {        lastName : "deng"//也会把原形东西拿出来,不想把原形拿出来————hasOwnProperty    }}for(var prop in obj) {    console.log(obj[prop]);    //console.log(obj['prop']);//跟obj.prop一样,这样也不对}

实现obj1里面属性+1返回
错误示范

var obj1 = {    a : 123,    b : 234,    c : 456}var key;for(key in obj1) {//这样写也行    obj1.key ++;}

1.hasOwnProperty(重点)

过滤性方法

判断这个属性是否是自己的(不是原形链的)
true
false

不想把原形拿出来demo

var obj = {    name : '13',    age : 123,    sex : "male",    height : 180,    weight : 178,    __proto__ : {        lastName : "deng"    }}for(var prop in obj) {    if(obj.hasOwnProperty(prop)){        console.log(obj[prop]);    }}

自己设的一定能打印,系统设的一定不能

var obj = {    name : '13',    age : 123,    sex : "male",    height : 180,    weight : 178,    __proto__ : {        lastName : "deng",        __proto__ : Object.prototype//一旦延展的原型链的最顶端,不会打印最顶端    }}

2.in

和hasOwnProperty类似

var obj = {    name : '13',    age : 123,    sex : "male",    height : 180,    weight : 178,    __proto__ : {        lastName : "deng"    }}//console.log(height in obj)//height叫变量console.log('height' in obj)//height这个属性名存不存在于objconcole.log('lastName' in obj)

和hasOwnProperty的区别:
In判断能不能访问到这个属性或者原形(只能判断对象上能不能访问到这个属性,也可以在父级找)
hasOwnProperty判断属性属不属于这个对象
开发从来不用

3.instanceof(重点)

function Person(){}var person = new Person();var obj = {};// A对象是不是B构造函数构造出来的console.log(person instanceof Person);// ---->ture

看A对象的的原型链上有么有B的原形(重点)

console.log(person instanceof Object);---->tureconsole.log([] instanceof Array);---->tureconsole.log([] instanceof Object);---->tureconsole.log(person instanceof Array);---->falseconsole.log(obj instanceof Person);---->false //两个没关系

解决的问题

判断变量是数组还是对象(机器识别)

typeof([])"object"typeof({})"object"//需求:var arr = [] || {};

第一种方法:

var obj = {};//var obj = [];obj.constructor//直接区分出来了

第二种方法:

[] instanceof Array   //truevar obj = {};obj instanceof Array //false

第三种方法:toString

Object.prototype.toString.call([]);//Object.prototype.toString = function (){//谁调用,this就是谁//识别this://返回相应结果//}// obj.toString();// call.toString();Object.prototype.toString.call([]);//数组会替换thisObject.prototype.toString.call(123);Object.prototype.toString.call({});//区别数组和对象

控制台验证

Object.prototype.toString.call([]);"[object Array]"Object.prototype.toString.call({})"[object Object]"Object.prototype.toString.call(123);"[object Number]"

this

1.函数预编译过程 this —> window

function test(c) {    //var this = Object.create(test.prototype);    //相当于    // {    //    __proto__ : test.prototype    // }    var a = 123;    function b(){}}//AO{//  arguments : [1],//自带的//  this : window,//自带的//  c : 1,//  a : undefined,//  b : function() {}//}test(1);new test();//new导致this指向发生了改变,不在是window了

验证

function test(){    console.log(this);}test();

2.全局作用域里 this —> window

console.log(window);

3.call/apply 可以改变函数运行时this指向

4.obj.f(); f()里面的this指向obj)

谁调用的方法,this就指向谁,如果没人调用这个方法,空执行,this是window

var obj = {    a : function () {        console.log(this.name)//谁调用,就用谁的name     },    name : 'abc'}obj.a();//obj调用

5.this题

条件判断为假的情况有: 0 、false 、’’ 、 null 、undefined 、未定义对象。
函数声明写在运算符中,其为 true,但 放在运算符中的函数声明在执行阶段时找不到的 。
另外,对未声明的变量执行 typeof 不会报错,会返回 undefined

this一马平川题

var name = "222";var a = {    name : "111",    say : function(){        console.log(this.name);    }}var fun = a.say;//a.say代表function的函数引用,fun在全局上执行,相当于函数在全局执行fun()//222全局执行也没人调用a.say()//111var b = {    name : "333",    say : function(fun){        //this---->b        fun();//不是this.fun(),谁也没调用,预编译,上面得this--->window,222    }}b.say(a.say);//a.say---是上面的函数体,       222b.say = a.say;//a.say上面的函数拷贝到b.say(代替b.say)b.say();//333

arguments

arguments.callee

func.caller

arguments

function test(){     console.log(arguments.callee); }test();//返回自己的函数体

应用:

var num = (function(n){    if(n == 1) {        return 1;    }    return n*阶乘(n-1);}(100))

立即执行函数的阶乘:只能用callee做

var num = (function(n){    if(n == 1) {        return 1;    }    return n*arguments.callee(n-1);}(100))

在那个函数里面,就打印哪个

function test(){    console.log(arguments.callee);    function demo(){        console.log(arguments.callee);    }    demo();}

caller: demo在哪个环境调用的

function test () {   demo();}function demo() {    console.log(demo.caller);}test();

克隆

1.浅层克隆

var obj = {    name : 'abc',    age : 123,    sex : 'female'}var obj1 = {}function clone(origin,target){    for(var prop in origin){        target[prop] = origin[prop];    }}clone(obj,obj1);//打印obj1显示已经copy过去了

实现容错:

var obj = {    name : 'abc',    age : 123,    sex : 'female'}var obj1 = {}function clone(origin,target){    var target = target || {};    for(var prop in origin){        target[prop] = origin[prop];    }    return target;}clone(obj,obj1);

原始值没问题,但是引用值拷贝:

var obj = {    name : 'abc',    age : 123,    sex : 'female',    card : ['visa', 'unionpay']}var obj1 = {}function clone(origin,target){    var target = target || {};    for(var prop in origin){        target[prop] = origin[prop];    }    return target;}clone(obj,obj1);

2.深层克隆

两个人,克隆,只考虑引用值的数组、对象 核心:区分数组和对象

var obj = {    name : 'abc',    age : 123,    sex : 'female',    card : ['visa','unionpay',[1,2]]}var obj1 = {    card : [obj.card[0],obj.card[1],[]]}clone(obj, obj1);
var obj = {    name : 'abc',    age : 123,    card : ['visa', 'master'],    wife : {        name : "bcd",        son : {            name : "aaa"        }    }}var obj1 = {    name : obj.name,    age : 123,    card : []//重新开始循环,发现里面都是原始值,card : [obj.card[0],obj.card[1]],    wife : {    name : "bcd",    son : {    name : "bcd",    son : }}//里面是不是原始值,第一个是,第二个不是, 建立新的对象,进行循环}

遍历对象 for(var prop in obj)
遍历除了可以遍历对象,还可以遍历数组

var arr = ['a','b','c']for(var prop in arr) {    arr[prop]}

步骤:

1.判断是不是原始值 typeof()如果是object引用值,不是obj,基本是原始值 null最后讲
2.数组还是对象 三种方法: instanceof toString constructor,建议使用toString,因为
另外两个有小问题,不会遇到
父子域:一个页面里面可能还有个子页面 跨父子域 [] instanceof Array ——>false应该ture
3.建立相应的数组和对象

// 递归function deepClone(origin,target) {    var target = target || {};//容错    toStr = Object.prototype.toString,        arrStr = "[object Array]";//比对}

代码实现

var obj = {    name : 'abc',    age : 123,    card : ['visa', 'master'],    wife : {        name : "bcd",        son : {            name : "aaa"        }    }}var obj1 = {}       function deepClone(origin,target) {    var target = target || {};//容错    toStr = Object.prototype.toString,        arrStr = "[object Array]";    for(var prop in origin) {        if(origin.hasOwnProperty(prop)) {//防止原型链上的            if(typeof(origin[prop]) == 'object') {                if(toStr.call(origin[prop]) == arrStr) {                    target[prop] = [];                }else{                    target[prop] = {};                }                deepClone(origin[prop],target[prop]);//递归            }else{                target[prop] = origin[prop];            }        }    }    return target;}

优化

function print(){    function deepClone(origin, target){        var target = target || {},            toStr = Object.prototype.toString,            arrStr = "[object Array]";        for(var prop in origin) {            if(origin.hasOwnProperty(prop)) {//null问题                if(origin[prop] !== "null" && typeof(origin[prop]) == 'object') {                    //绝对不等于,隐式类型转换也不行                    if(toStr.call(origin[prop]) == arrStr) {                        target[prop] == [];                    }else{                        target[prop] = {};                    }                    deepClone(origin[prop],target[prop]);                }else{                    target[prop] = origin[prop];                }            }        }        return target;    }

三目运算符简化代码

function print(){    function deepClone(origin, target){        var target = target || {},            toStr = Object.prototype.toString,            arrStr = "[object Array]";        for(var prop in origin) {            if(origin.hasOwnProperty(prop)) {//null问题                if(origin[prop] !== "null" && typeof(origin[prop]) == 'object') {                    //绝对不等于,隐式类型转换也不行                    target[prop] = (toStr.call(origin[prop]) == arrStr) ? [] : {};                    deepClone(origin[prop],target[prop]);                }else{                    target[prop] = origin[prop];                }            }        }        return target;    }

数组

数组的定义

区分对象的定义方式
(1) 自面量
(2) 构造函数——系统自带
(3) 自定义构造函数
(4) Var Obect.create()

数组
1.数组字面量 var arr = [];

var arr = [1,2,3,,,5];//稀松数组

2.new Array(length/content);

构造方法   var arr = new Array(1,2,3,4,5);

区别

var arr = new Array(10);//返回长度为10的稀松数组var arr1 = [10]; var arr = new Array(10.2);//长度为10.2 报错

数组的读和写

arr[num] //不可以溢出读   结果undefinedarr[num] = xxx;//可以溢出写,撑长数组

JS中,数组就算没有第10位也不报错,因为数组是基于对象的
数组常用的方法

1.改变原数组7个

reverse,sort,push,pop,shift,unshift,

push把数组的最后一位增加

封装push()

var arr = [1,2,3];Array.prototype.push = function (){//不能写形参,因为不知道有几个,所以只能用arguments    for(var i = 0; i < arguments.length; i++) {        this[this.length] = arguments[i];    }    return this.length;}

pop删除:把数组的最后一位剪切出去

arr.pop(); 不能传参

shift:把前面减 arr.shift()

unshift:和push方向相反,在前面加东西

封装unshift

数组不能向前面放东西,所以用新数组,在拼接起来(concat)

reverse:逆反

sort

arr.sort();//升序排序

arr.sort().reverse()//降序

但是这个排序是按ASCII排的,so
var arr = [1,2,10,2,4,5];不能实现想要的排序
实现排序:(冒泡排序)
1.必须两个形参
2.看返回值

(1)返回值为负数,前面的数放在前面
(2)为正数,后面的数在前
(3)为0,不动

var arr = [1,2,10,2,4,5];arr.sort(function (a, b) {    if(a > b) {        return 1;    }else{        return -1;    }});

简化代码

arr.sort(function (a, b) {    if(a - b > 0) {        return a - b;    }else{        return a - b;    }});

最终

arr.sort(function (a, b) {    return a - b;//升序    //return b - a;//降序});

给一个有序数组乱序

Math.random()    返回(0,1)随机数// var arr = [1,2,3,4,5,6,7];// arr.sort(function () {//     return Math.random() - 0.5;//实现可正可负// });

对象年龄排序

var cheng = {    name : "cheng",    age : 18,    sex : 'male',    face : "handsome"}var deng = {    name : "deng",    age : 40,    sex : undefined,    face : "amazing"}var zhang = {    name = "zhang",    age = 20,    sex = "male"}var arr = [cheng, deng, zhang];arr.sort(function (a, b) {    // if(a.age > b.age) {    //  return 1;    // }else{    //    return -1;    // }    return a.age - b.age;}

字符串长度排序

var arr = ['ac','bcd','cccc','asfsadshilk','casuicbniasbnciuas'];arr.sort(function (a, b){    return a.length - b.length;})

字节长度排序

function retBytes(str) {    var num = str.length;    for(var i = 0; i < str.length; i++){        if(str.charCodeAt(i) > 255){            num ++;        }    }    return num;}var arr = ['a邓','ba邓','cc邓cc','老邓',"残邓",'asdoifqwoeiur','asdf'];arr.sort(function (a, b){    return retBytes(a)-retBytes(b);})

splice:切片

// arr.splice(从第几位开始,剪切多少长度,在切口处添加新的数据)arr.splice(1,2);demovar arr = [1,1,2,2,3,3];arr.splice(1,1,0,0,0);var arr = [1,2,3,5];//实现把4填进去arr.splice(3,0,4);//鼠标光标在前面arr.splice(-1,1);//倒数第一位

-1倒数第一位;1倒数 第二位怎么实现的

splice = function(pos) {pos += pos>0?0:this.length;    //负数}

2.不改变原数组

concat,join—>split,toString

  1. concat连接
var arr = [1,2,3,4,5,6];var arr1 = [7,8,9];arr.concat(arr1);

toString

把数组变成字符串

Slice截取

var arr = [1,2,3,4,5,6];// 1.两个参数,slice(从该位开始截取,截取到该位)// var newArr = arr.slice(1,3);// 2.一个参数slice(从第几位开始截取,截取到最后)var newArr = arr.slice(1)var newArr = arr.slice(-4)//-4+6位// 3.没参数:全截取

join

实现字符串连接

var arr = [1,2,3,4];arr.join("-")//必须是字符串形式arr = [1-2-3-4];

split()互逆方法:按照什么拆分

var arr = [1-2-3-4];arr.split("3")//必须是字符串形式

类数组

是对象,可以当数组一样用

类数组
1.可以利用属性名模拟数组的特性
2.可以动态的增长length属性
3.如果强行让类数组调用push方法,则会根据length属性值的位置进行属性的扩充。

function test() {    console.log(arguments);    arguments.push(7);//报错}test(1,2,3,4,5,6);

现象

//完成类数组的基本形态构建var obj = {    "0" : 'a',    "1" : 'b',    "2" : 'c',    "length" : 3,    "push" : Array.prototype.push}obj.push('d');//导致length=4并且"3":d

类数组:是对象,可以当数组一样用

var obj = {    "0" : 'a',    "1" : 'b',    "2" : 'c',    "length" : 3,    "push" : Array.prototype.push,    "splice" : Array.prototype.splice//加上他就变成可以当数组用了,像数组了}//类数组组成部分:属性要为索引(数字)属性,必须有length属性,最好加上push

length内部操作手法:

Array.prototype.push = function(target) {    this[this.length] = target;    this.length ++;}//如果对象调用,则Array.prototype.push = function(target) {    obj[obj.length] = target;    obj.length ++;}

类数组所有元素遍历出来

var obj = {    "0" : "a",    "1" : "b",    "2" : "c",    name : "abc",    age : 123,    length : 3,    push : Array.prototype.push,    splice : Array.prototype.splice}for(var prop in obj){    console.log(obj[prop])}

封装type

typeof([])-- array
typeof({})-- object
typeof(function)-- function
typeof(new Number())-- new Object
typeof(123)-- number
分两类:1、原始值 引用值 2、区分引用值

function type(target) {    var template = {        "[object Array]" : "array",        "[object Object]" : "object",        "[object Number]" : "number - object",        "[object Boolean]" : 'boolean - object',        "[object String]" : 'string - object'    }    if(target === null){        return "null";    }    // if(typeof(target) == 'function') {    //  return 'function';    // }else if(typeof(target) == "object") = {    if(typeof(target) == "object"){        // 数组;        // 对象;        // 包装类Object.prototype.toString        var str = Object.prototype.toString.call(target);        return template[str];    }else{//原始值        return typeof(target);    }

数组去重,在原型链上编程​ hash哈西

var arr = [1,1,1,1,2,2,2,2,2,1,1,1,0,0];Array.prototype.unique = function() {    var temp = {},        arr = [],        len = this.length;//也是优化,不用每次都this了    for(var i = 0; i < len; i++){        if(!temp[this[i]]) {//如果有0,!0==true,所以还是"abc"吧            temp[this[i]] = "abc";            arr.push(this[i]);        }    }    return arr;}

三目运算符

形式:判断语句? 若为真,执行,并返回结果:若为假,执行,并返回结果
三目运算符其实就是简化版的if(){…}else{}语句
条件判断?是 :否 并且会返回值

var num = 1 > 0 ? 2 + 2 : 1 + 1;var num = 1 > 0 ? ("10" > "9" ? 1 : 0) : 2;

try…catch

try{}catch(e) {}一行代码报错影响后面代码执行

finally{}

//try...catchtry{    console.log('a');    console.log(b);    console.log('c');}catch(e) {}console.log('d');//执行到b就不执行了,在try里面发生的错误,不会执行错误后的try里面的代码,打印ad

关于catch

try{    console.log('a');    console.log(b);    console.log('c');}catch(e){//error  error.message  error.name ---> error    console.log(e.name + " : " + e.message);  }console.log('d');

小问题

try{    console.log('a');    console.log(b);    console.log(c);//虽然错误,但是不执行}catch(e){    console.log(e.name + " : " + e.message);   }console.log('d');

Error.name的六种值对应的信息:
1.EvalError:eval()的使用与定义不一致
2.RangeError:数值越界
3.ReferenceError:非法或不能识别的引用数值
4.SyntaxError:发生语法解析错误
5.TypeError:操作数类型错误
6.URIError:URI处理函数使用不当

es5严格模式

如今:基于es3.0+es5.0的新增方法 使用的,如果产生冲突,则遵循es3.0的
要讲的是怎么让他遵循es5.0解决,即es5.0的严格模式,则产生冲突的部分用es5.0,否则es3.0
“use strict”
不再兼容es3的一些不规则语法。使用全新的es5规范。
demo1:es5不允许使用arguments.callee

// es5.0严格模式的启动"use strict"//放在逻辑的最顶端function test() {    console.log(arguments.callee);}test();

demo2

function demo() {    console.log(arguments.callee);}demo();//es3.0function test() {    "use strict"//内部es5.0    console.log(arguments.callee);}test();

两种用法:
全局严格模式
局部函数内严格模式(推荐)
就是一行字符串,不会对不兼容严格模式的浏览器产生影响
为什么用字符串"use strict":可能在老浏览器执行,浏览器版本问题——向后兼容
es5不允许用with(){} with可以改变作用域链,with(obj) obj作为最顶端的AO

var obj = {    name : "obj"}var name = 'window';function test() {    var name = 'scope';    with(obj) {//如果with里面添加了对象,with(obj),会把对象当做with要执行的代码体的作用域链的最顶端        console.log(name);    }}test();

演示

var obj = {    name:"obj",    age:234}var name = "window";function test(){    var age = 123;    var name = "scope";    with(obj){        console.log(name);//obj        console.log(age);//234    }}test();

with作用:简化代码

var org = {    dp1 : {        jc : {            name : 'abc',            age : 123        },        deng : {            name : "xiaodneg",            age : 234        }    },    dp2 : {    }}with(org.dp1.jc) {//直接访问org.dp1.jc里面的    console.log(name);}

应用:document也是对象

document{    write : function () {}}with(document) {    write('a');}

不支持with,arguments.callee,func.caller,变量赋值前必须声明,局部this必须被赋值,(Person.call(null/undefined) 赋值什么就是什么),拒绝重复属性和参数

"use strict"function test(){    console.log(this);//undefined}test();

new了

"use strict"function Test(){    console.log(this);//控制台显示constructor的名}new Test();

预编译在es5严格模式下this不在指向window,没有指向(空),this必须被赋值,赋值什么就是什么

"use strict"function Test(){    console.log(this);}Test.call({});

赋值123

"use strict"function Test(){    console.log(this);}Test.call(123);

123是原始值:ES3就会变成包装类

function Test(){    console.log(this);}Test.call(123);

严格模式,在全局,this指向window

"use strict"console.log(this);

es5拒绝重复属性和参数。。es3里面重复属性和参数是不报错的

function test (name , name){    console.log(name);}//test(1,2);//test(2);

参数报错

"use strict"function test (name , name){    console.log(name);}test(1,2);

属性不报错

"use strict"var obj={    name:'112',    name:'111'}test(1,2);

关于eval:

  1. es3不能用eval();——能改变作用域

  2. eval能执行字符串

"use strict";var a = 123;eval('console.log(a)');//字符串在eval里面执行

面试题:为什么不用with();

with可以改变作用域链,改变作用域链,都会降低效率

青春在线内部文档https://www.yuque.com/docs/share/7773dc1a-cd7d-4bf2-9b5a-170194ad9a56
MDN网站

原生JS 对象 包装类 原形 原型链相关推荐

  1. JS 面向对象编程、原型链、原型继承(个人学习总结)

    一.面向对象 1. 面向对象 是所有语言 都有的一种编程思想,组织代码的一种形式 基于对象的语言:JS语言 面向对象的语言:c++ java c# 2. 面向对象 3大特征 封装:将重用代码封装到函数 ...

  2. javaScript核心学习 (二)函数和对象,继承原型链

    javaScript的函数和对象,继承原型链 一.函数 1.初始函数 2.创建函数 2.1 参数设置 2.2 函数声明 来创建函数 2.3 函数表达式创建函数 3.变量作用域 4.匿名函数 5.回调函 ...

  3. vue js 对象下的原型_如何使用Vue.js和Pusher创建实时原型反馈应用程序

    vue js 对象下的原型 by Neo Ighodaro 由新Ighodaro 如何使用Vue.js和Pusher创建实时原型反馈应用程序 (How to create a realtime pro ...

  4. [js高手之路]原型对象(prototype)与原型链相关属性与方法详解

    一,instanceof: instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型. 我在之前的两篇文章 [js高手之路]构造函数的基本特性与优缺点 [js高手 ...

  5. js 中对象--对象结构(原型链基础解析)

    对于本篇对于如何自定义对象.和对象相关的属性操作不了解的话,可以查我对这两篇博客.了解这两篇可以更容易理解本篇文章 用构造函数创建了一个对象 obj对象的本身创建了两个属性  x=1   ,y=2 对 ...

  6. js的继承和原型链(更新中)

    话不多说,直接上MDN链接 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_ ...

  7. 深入理解 js 之继承与原型链

    原型链与继承 当谈到继承时,JavaScript 只有一种结构:对象.每个实例对象(object )都有一个私有属性(称之为proto)指向它的原型对象(prototype).该原型对象也有一个自己的 ...

  8. javascript数据类型,对象,继承及原型链

    楔子 说起来我不是个很好学的人,每每遇到学不懂的东西,就抓耳挠腮,左顾右盼,恨不得有个神仙立马出现抓起书上的东西一把塞进我脑子里,然后我就会了.省的又要记又要理解该多好.可我也明白这只不过梦里的事,Y ...

  9. 【js细节剖析】通过=操作符为对象添加新属性时,结果会受到原型链上的同名属性影响...

    在使用JavaScript的过程中,通过"="操作符为对象添加新属性是很常见的操作:obj.newProp = 'value';.但是,这个操作的结果实际上会受到原型链上的同名属性 ...

最新文章

  1. 「SAP技术」SAP 如何看序列号被包在哪些HU里?
  2. 配置windows失败,不能进入系统
  3. 60. Leetcode 面试题 10.03. 搜索旋转数组 (二分查找-局部有序)
  4. android中几种定位方式详解
  5. mysql 账户管理_Mysql账户管理原理与实现方法详解
  6. mysql乐观锁与事务_Mysql中的读锁,写锁,乐观锁及事务隔离级别和并发问题
  7. 冲击年薪50万的AI学习指南,限时免费~
  8. BootstrapTable的使用教程
  9. cs6导入库闪退 flash_flash cs6源文件怎么修复,导入老跳出意外格式,我是用flash cs6做的。我还有一半没有导出 swf 呢?...
  10. 小米平板2wifi驱动下载_Xiaomi小米随身WiFi驱动下载
  11. PMP考试答题技巧-模拟题库
  12. PPT:动画出现设置
  13. 数美科技:全栈防御体系怎么样护航游戏ROI增长
  14. 虚拟机Oracle VM VirtualBox 共享文件夹放的文件打不开,找不到指定路径问题
  15. oracle现金流量表逻辑,财务学习:现金流量表内在逻辑研究
  16. 1237 -- 地盘划分
  17. Linux第7章Gdk及Cairo基础,GNOME 平台的2D图形编程(GTK,GDK,Cairo...) 简介 [转]...
  18. jQuery特效,网站模板,商城模板,网页特效各种前端源码免费下载
  19. RTX 3060 快速配置GPU版本tensorflow
  20. mes系统多少钱,企业要不要上mes系统?

热门文章

  1. C. Web of Lies cf#736Div.2
  2. windows dism命令镜像修复方法
  3. jzoj5245 【NOIP2017模拟8.8A组】Competing Souls
  4. 2021SC@SDUSC-PALISADE(九)BGV的API分析
  5. jfif格式的图片怎么改成jpg
  6. 2020-03-29-近红外数据格式转换
  7. CCPC2019吉林省赛东北地区赛游记
  8. linux 预览md文件_微软 Win10 Dev 预览版 20246 发布:来自最新 FE_RELEASE 开发分支 - Windows 10,微软...
  9. 分布式事务:Alibaba Seata 如何实现分布式事务
  10. jmeter设置中文