ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## **声明对象** ``` //内置函数 之 Object构造函数模式 var p=new Object(); p.name='dash'; p.age=20; p.setName=function(name){ this.name=name } //字面量 var Persion2={ name:"dash2", age:21, say2:function(){ console.log(this.name+this.age) }, china:{ name:"李磊", age:18, eat:function(){ console.log(this.name+"吃了黄焖鸡"); } } } console.log(Persion2); Persion2.say2(); Persion2.china.eat(); // 自定义构造函数 function Persion(name,age){ this.name=name; this.age=age; this.say3=function(){ console.log(this.name+this.age) } } var Persion3=new Persion("dash3",21); console.log(Persion3); Persion3.say3(); //返回一个对象的函数工厂函数(一般不常用) function Persion(name,age){ var obj={ name:name, age:age, setName:function(name){ this.name=name; } } return obj; } var Persion3=new Persion("dash3",21); // Es6类 class Persion2{ constructor(name,age){ this.name=name; this.age=age; } say4(){ console.log(this.name+this.age) } } var Persion4=new Persion2("dash4",21); console.log(Persion4); Persion4.say4(); //使用Object.create(proto=null) //该方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ var person={ image:"true", say5:function(){ console.log(`名字是${this.name},年龄是${this.age}`); } } var Persion5=Object.create(person); Persion5.name="dash5"; Persion5.age=21; Persion5.image=false; Persion5.say5(); console.log(Persion5) Object.create //Object.create()方法创建的对象时,属性是在原型下面的 //而new Object()创建的对象是 Object的实例,原型永远指向Object.prototype //new Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。 //Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。 // new Object() 方式创建 var a = { rep : 'apple' } var b = new Object(a) console.log(b) // {rep: "apple"} console.log(b.__proto__) // {} console.log(b.rep) // {rep: "apple"} // Object.create() 方式创建 var a = { rep: 'apple' } var b = Object.create(a) console.log(b) // {} console.log(b.__proto__) // {rep: "apple"} console.log(b.rep) // {rep: "apple"} ``` 推荐:构造+原型 ``` function Person(name,age){ this.name=name; this.age=age; } Person.prototype.setName=function(name){ this.name=name; } var p1=new Person('dash',18); var p2=newcperson('tom',28); ``` 对象的属性除了obj.属性名,还可以obj['属性名']表示,obj['属性名']可以定义特殊的属性名如:obj['123']不会报错,而obj.123则会报错,obj['属性名']还可以传递变量如:`var name="dash";obj[name];` 函数对象和实例对象不一样 ``` function person(){ } //向函数对象追加属性 person.name="tom"; person.say=function(){console.log("hello world!")} //向原型对象追加属性(实例对象可访问)相当于向父类追加属性 person.prototype.sex="男"; var p=new person(); console.log(p.name);//undefined console.log(p.sex);//男 ``` ## ### **检测对象中的属性 in和hasOwnProperty** 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true 可以使用对象的hasOwnProperty ()来检查对象自身中是否含有该属性使用该方法只有当对象自身中含有属性时,才会返回true ``` var obj=new Object(); obj.name="dash"; Object.prototype.sex="男"; var a= "name" in obj; console.log(a);//true var a =obj.hasOwnProperty("name"); console.log(a);//true var b= "age" in obj; console.log(b);//false var c= "sex" in obj; console.log(c);//true var d =obj.hasOwnProperty("sex"); console.log(d);//false ``` ## ### **构造函数** 构造函数和普通函数的区别就是调用方式的不同: 普通函数是直接调用,而构造函数需要使用new关键字来调用 构造函数和new 类关键字大小写要一致 构造函数的执行流程:. * 1.立刻创建一个新的对象 * 2.将新建的对象设置为函数中this,在构造函数中就可以用this来代表这个新建的对象 * 3.逐行执行函数中的代码 * 4 将新建的对象作为返回值返回 构造函数组成部分:`一个普通函数`+**new** `这个普通函数名` ``` function Demo(){ console.log(this) } var d=new demo(); ``` 创建一个person构造函数-在person构造函数中,为每一个对象都添加了一个sayName方法 ``` function person(name, age, sex){ this.name=name; this.age=age this.sex=sex; this.sayName=function(){ console.log(this.name); } } var p1=new person("dash",18,"男"); var p2=new person("yinli",18,"女"); ``` 目前我们的方法是在构造函数内部创建的,也就是构造函数每执行一次就会创建一个新的sayName方法也是所有实例的sayName都是唯一的。这样就导致了构造函数执行一次就会创建一个新的方法,执行10000次就会创建10000个新的方法且都是一模一样的,这个完全没必要,完全可以使用所有的对象共享同一个方法 ``` function person(name, age, sex){ this.name=name; this.age=age this.sex=sex; this.sayName=fun; } //将sayName在全局作用域中定义(缺点:污染全局作用域的命名空间 请使用原型对象) function fun(){ console.log(this.name); } var p1=new person("dash",18,"男"); var p2=new person("yinli",18,"女"); ``` ## ## **原型对象** 显示原型属性prototype与隐式原型属性__proto__都指向这个原型对象 ```js function demo(){}//相当于var demo=new Function() demo.prototype;//{constructor:demo,__proto__:Object} //每个函数(对象)都有prototype属性,他指向一个Object空对象 JSON.stringify(demo.prototype)//{} //原型对象prototype中有个constructor指向函数对象 demo.prototype.constructor===demo;//true //这个属于Object的实例对象object类型的原型对象的constructor属性指向Function的实例对象function,__proto__属性指向Object的实例对象object var po=demo.prototype; typeof po;//object typeof po.constructor//function typeof po.__proto__//object demo.prototype.__proto__==demo.prototype;//fasle var d=new demo(); d.__proto__==demo.prototype;//true ``` ![](https://img.kancloud.cn/5a/b8/5ab86c892375b2145b817a1da2d42f56_813x397.png) ## **函数的显式原型属性** 函数的prototype属性(即显式原型) * 每个函数都有一个prototype 属性, 它默认指向一object空对象(即称为: 原型对象), * 原型对象中有一个属性constructor,它指向函数对象 给原型对象添加属性(一般都是方法) 作用:函数的所有实例对象自动拥有原型中的属性(方法) 我们创建的每一个函数,解析器就会像该函数添加一个prototype属性,这个**prototype属性对应着一个对象,这个对象就是所谓的原型对象** ![](https://img.kancloud.cn/94/71/9471ebce49664f7d9413265ea83a1de5_774x81.png) ``` function MyClass(){} console.log(MyClass.prototype); ``` ## **对象的隐式原型属性** 对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值程 序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前) 当函数以构造函数的形式调用时(即new函数 ),它所创建的对象(函数实例对象)中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__来访问该属性 ``` function MyClass(){} var mc=new MyClass(); console.log(mc.__proto__); console.log(mc.__proto__==MyClass.prototype);//true ``` ![](https://img.kancloud.cn/a7/2d/a72d72fe9aa21558f3ab55e9d8319ff6_783x209.png) 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中 共有的内容,统一设置到原型对象中。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,·这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法 ``` function person(name, age, sex){ this.name=name; this.age=age this.sex=sex; } person.prototype.sayName=function(){ console.log(this.name); } var p1=new person("dash",18,"男"); var p2=new person("yinli",18,"女"); ``` ## ## **原型链(别名:隐式原型链)** 原型对象也是对象,所以它也有原型,当我们使用一个对象的属性或方法时,会现在自身中寻找,自身中如果有,则直接使用,如果没有则去原型对象中寻找,如果原型对象中与,则使用,如果没有则去原型的原型中寻找,直到找到Object的对象的原型 如访问一个对象的属性时,先在自身属性中查找,找到返回如果没有,再沿着_proto_这条链向上查找,找到返回 如果最终没找到,返回undefined ``` function MyClass(){ this.name="dash"; } MyClass.prototype.a=123; var mc=new MyClass(); var mc2=new MyClass(); var mc3=new MyClass(); console.log(mc.hasOwnProperty("name"));//true console.log("name" in mc);//true console.log("a" in mc);//true console.log(mc.hasOwnProperty("a"));//false console.log(mc.hasOwnProperty("hasOwnProperty"));//false console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true console.log(mc.__proto__);//MyClass console.log(mc.__proto__.__proto__);//Object ``` ![](https://img.kancloud.cn/ae/76/ae76218f1ac2d30817c439048a1599a8_774x467.png) ![](https://img.kancloud.cn/d9/df/d9df4d7999046ba6705a85895fb8af29_1289x512.png) >[danger]注意区分函数对象与实例对象与函数对象 **构造函数原型实例对象的关系** 当函数以构造函数的形式调用(new)时,它所创建的对象中都会有一个隐含的属性__proto__,指向该构造函数的原型对象(prototype 属性, 它默认指向一object空对象 即称为: 原型对象),原型对象中有一个属性constructor,它指向函数对象 ``` var o1=new Object(); var o2={}; ``` 所有函数都是Function的示例(包括Function自身) ``` Function.__proto__===Function.prototype//true ``` 函数(函数对象)的显示原型与实例对象的隐式原型都指向Object空对象(Object例外) object是原型链的尽头,object.prototype.__proto__为null ![](https://img.kancloud.cn/41/dc/41dc2c54651fe480ac38c67b17c7c4d5_1044x377.png) 函数也是个实例对象,准确的说他是 Function的实例对象 即每个 JavaScript 函数实际上都是一个`Function`对象。运行`(function(){}).constructor === Function // true`便可以得到这个结论 ``` function Foo(){}//相当于 var Foo =new Function(); ``` 实例对象的隐式原型等于构造函数的显式原型 ![](https://img.kancloud.cn/6a/29/6a2982606029c07c1c2c474f60718fe6_800x856.png) 当我们直接在页面中打印一个对象时实际上是输出的对象的tostring()方法的返回值 ``` function person(name, age, sex){ this.name=name; this.age=age this.sex=sex; this.sayName=fun; } person.prototype.sayName=function(){ console.log(this.name); } var p1=new person("dash",18,"男"); var p2=new person("yinli",18,"女"); console.log(p1); console.log(p1.toString()); ``` 练习: ``` function Demo(){} Demo.prototype.n=1; var d1=new Demo(); Demo.prototype={ n:2, m:3 } var d2=new Demo(); console.log(d1.n, d1.m, d2.n, d2.m);//1 undefined 2 3 ``` 练习2 ``` var F=function(){}; Object.prototype.a=function(){ console.log("a"); } Function.prototype.b=function(){ console.log("b"); } var f=new F(); f.a();//a f.b();//Uncaught TypeError: f.b is not a function F.a();//a F.b();//b ``` **探索instanceof** ``` function Foo(){}; var f1=new Foo(); console.log(f1 instanceof Foo);//true console.log(f1 instanceof Object);//true ```